题意是有n座城市,n号城市不想让1号城市可达n号,每条道路有一条毁坏的代价,1号还可以修一条不能毁坏的道路,求n号城市所需的最小代价最大是多少。

毁坏的最小代价就直接求一遍最大流,就是最小割了。而可以修一条不能毁坏的路,需要枚举的这些边就是源集中的点到汇集中的点,我之前的做法是直接找出所有的割边,再枚举每一条割边,在这两个点上加一个流量为无穷大的边再去求最大流,实际上这样连样例的第二个数据都过不了,因为图不保证是连通的,那就有一些源集中的点和汇集中的点本来就不联通,就不存在这样的割边了。发现这个错误后,我就在没有联通的所有边中加了一条cap为0的边,想弥补上面的bug,但是这样的话超时了。奇怪的是,我没有加那些cap为0的点的时候也是超时而不是wa。

所以就找出所有的源点,找出所有的汇点,去除1和n后枚举这些边在原来的基础上去跑最大流,得出来的意义就是如果修的是这条路,所需要的额外的代价。

我自己的代码不知道为什么过不了,可能是模板的问题?

贴两个代码吧,前面是自己的,后面是别人的。

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <fstream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <deque>
  7 #include <vector>
  8 #include <queue>
  9 #include <string>
 10 #include <cstring>
 11 #include <map>
 12 #include <stack>
 13 #include <set>
 14 #define LL long long
 15 #define eps 1e-8
 16 #define INF 0x3f3f3f3f
 17 #define MAXN 105
 18 #define OPEN_FILE
 19 using namespace std;
 20 int S;
 21 struct Edge{
 22     int from, to, cap, flow;
 23     //Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f){};
 24 };
 25 vector<Edge> cutset;
 26 bool comp(const Edge& a, const Edge& b){
 27     return (a.from < b.from || (a.from == b.from && a.to < b.to));
 28 }
 29 struct Dinic{
 30     int n, m, i, s, t;
 31     Edge e;
 32     vector<Edge> edges;
 33     vector<int> G[MAXN];
 34     int d[MAXN], cur[MAXN];
 35 //    bool vis[MAXN];
 36     int Q[MAXN * 10];
 37 
 38     void init(int n){
 39         this->n = n;
 40         for (i = 0; i <= n; i++){
 41             G[i].clear();
 42         }
 43         edges.clear();
 44     }
 45     void AddEdge(int from, int to, int cap){
 46         edges.push_back(Edge{ from, to, cap, 0 });
 47         edges.push_back(Edge{ to, from, 0, 0 });
 48         m = edges.size();
 49         G[from].push_back(m - 2);
 50         G[to].push_back(m - 1);
 51     }
 52     bool BFS(){
 53     //    memset(vis, 0, sizeof(vis));
 54         int head = 0, tail = 0;
 55         Q[head] = s;
 56         memset(d, 0, sizeof(d));
 57         d[s] = 1;
 58         S = 0;
 59         while (head <= tail){
 60             int x = Q[head++];
 61             for (i = 0; i < G[x].size(); i++){
 62                 Edge& e = edges[G[x][i]];
 63                 if (d[e.to] == 0 && e.cap > e.flow){
 64                     d[e.to] = d[x] + 1;
 65                     Q[++tail] = e.to;
 66                     S++;
 67                 }
 68             }
 69         }
 70         if (d[t] == 0){
 71             return false;
 72         }
 73         else{
 74             return true;
 75         }
 76     }
 77     int DFS(int x, int a){
 78         if (x == t || a == 0) return a;
 79         int flow = 0, f;
 80         for (int& i = cur[x]; i < G[x].size(); i++){
 81             Edge& e = edges[G[x][i]];
 82             if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0){
 83                 e.flow += f;
 84                 edges[G[x][i] ^ 1].flow -= f;
 85                 flow += f;
 86                 a -= f;
 87                 if (a == 0) break;
 88             }
 89         }
 90         return flow;
 91     }
 92     int MaxFlow(int s, int t, int need){
 93         int flow = 0;
 94         this->s = s;
 95         this->t = t;
 96         while (BFS()){
 97             memset(cur, 0, sizeof(cur));
 98             flow += DFS(s, INF);
 99             if (flow > need) return flow;
100         }
101         return flow;
102     }
103 };
104 int n, m;
105 Dinic p, q;
106 int RIGHT[MAXN];
107 int main()
108 {
109 #ifdef OPEN_FILE
110     freopen("in.txt", "r", stdin);
111     //freopen("out.txt", "w", stdout);
112 #endif // OPEN_FILE
113     int T;
114     scanf("%d", &T);
115     for (int cas = 1; cas <= T; cas++){
116         scanf("%d%d", &n, &m);
117         p.init(n);
118         int x, y, z;
119     //    memset(conn, 0, sizeof(conn));
120         for (int i = 1; i <= m; i++){
121             scanf("%d%d%d", &x, &y, &z);
122             p.AddEdge(x, y, z);
123         //    conn[x][y] = true;
124             //conn[y][x] = true;
125         }
126         //int res = p.MaxFlow(1, n, INF);
127         //p.AddEdge(2, 3, INF);
128         //q = p;
129         int res = p.MaxFlow(1, n, INF);
130         int cnt = 1;
131     //    memset(isR, 0, sizeof(isR));
132         for (int i = 2; i < n; i++){
133             if (p.d[i] == 0){
134                 RIGHT[cnt++] = i;
135             }
136         }
137         cnt--;
138         int ans = 0;
139         for (int i = 0; i <= S; i++){
140             if (p.Q[i] == 1 || p.Q[i] == n) continue;
141             for (int j = 1; j <= cnt; j++){
142                 q = p;    
143                 q.AddEdge(p.Q[i], RIGHT[j], INF);
144                 int o = q.MaxFlow(1, n, INF);
145                 ans = max(ans, o);
146             }
147         }
148 //         int ans = 0;
149 //         for (int i = 0; i < cutset.size(); i++){
150 //             q = p;
151 //             q.AddEdge(cutset[i].from, cutset[i].to, INF);
152 //             int o = q.MaxFlow(1, n, INF);
153 //             ans = max(ans, o);
154 //         }
155         printf("%d\n", ans + res);
156         //    printf("%d\n", p.MaxFlow(1, n, INF));
157     }
158 }
View Code

相关文章: