HDU 2435 There is a war Dinic 最小割

题意是有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
", ans + res);
156         //    printf("%d
", p.MaxFlow(1, n, INF));
157     }
158 }
View Code
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<set>
  5 #include<cstdio>
  6 #include<string>
  7 #include <algorithm>
  8 using namespace std;
  9 const int maxn = 105;
 10 //const int maxm=300006;
 11 const int inf = 1 << 30;    
 12 
 13 
 14 struct node
 15 {
 16     int v, next;
 17     int val;
 18 };
 19 int topset;
 20 struct dinic{
 21     node s[maxn*maxn * 2];
 22 
 23 
 24     int level[maxn];//顶点的层次
 25     int p[maxn];
 26     int que[maxn * 10];//BFS中用于遍历的顶点,DFS求增广中记录边
 27     int out[10 * maxn];//DFS用于几乎定点的分支
 28     int ind;
 29 
 30 
 31     int cop_poit[maxn];
 32     node cop_mp[maxn*maxn * 2];
 33 
 34 
 35 
 36     void init()
 37     {
 38         ind = 0;
 39         memset(p, -1, sizeof(p));
 40     }
 41 
 42 
 43     inline void insert(int x, int y, int z)
 44     {
 45         s[ind].v = y;
 46         s[ind].val = z;
 47         s[ind].next = p[x];
 48         p[x] = ind++;
 49         s[ind].v = x;
 50         s[ind].val = 0;
 51         s[ind].next = p[y];
 52         p[y] = ind++;
 53     }
 54 
 55 
 56     int max_flow(int n, int source, int sink)
 57     {
 58         int ret = 0;
 59         int h = 0, r = 0;
 60         while (1)//DFS
 61         {
 62             int i;
 63             for (i = 0; i <= n; ++i)
 64                 level[i] = 0;
 65             h = 0, r = 0;
 66             level[source] = 1;
 67             que[0] = source;
 68             while (h <= r)//BFS
 69             {
 70                 int  t = que[h++];
 71                 for (i = p[t]; i != -1; i = s[i].next)
 72                 {
 73                     if (s[i].val&&level[s[i].v] == 0)
 74                     {
 75                         level[s[i].v] = level[t] + 1;
 76                         que[++r] = s[i].v;
 77                     }
 78                 }
 79             }
 80             topset = r;//记录原点的集合个数
 81 
 82 
 83             if (level[sink] == 0)break;//找不到汇点
 84             for (i = 0; i <= n; ++i)
 85                 out[i] = p[i];
 86 
 87 
 88             int  q = -1;
 89             while (1)
 90             {
 91                 if (q < 0)
 92                 {
 93                     int  cur = out[source];
 94                     for (; cur != -1; cur = s[cur].next)
 95                     {
 96                         if (s[cur].val&&out[s[cur].v] != -1 && level[s[cur].v] == 2)
 97                         {
 98                             break;
 99                         }
100                     }
101                     if (cur >= 0)
102                     {
103                         que[++q] = cur;
104                         out[source] = s[cur].next;
105                     }
106                     else
107                     {
108                         break;
109                     }
110                 }
111 
112 
113                 int  u = s[que[q]].v;
114 
115 
116                 if (u == sink)//一条增广路
117                 {
118                     int  dd = inf;
119                     int  index = -1;
120                     for (i = 0; i <= q; i++)
121                     {
122                         if (dd > s[que[i]].val)
123                         {
124                             dd = s[que[i]].val;
125                             index = i;
126                         }
127                     }
128                     ret += dd;
129                     //cout<<ret<<endl;
130                     for (i = 0; i <= q; i++)
131                     {
132                         s[que[i]].val -= dd;
133                         s[que[i] ^ 1].val += dd;
134                     }
135                     for (i = 0; i <= q; i++)
136                     {
137                         if (s[que[i]].val == 0)
138                         {
139                             q = index - 1;
140                             break;
141                         }
142                     }
143                 }
144                 else
145                 {
146                     long cur = out[u];
147                     for (; cur != -1; cur = s[cur].next)
148                     {
149                         if (s[cur].val&&out[s[cur].v] != -1 && level[u] + 1 == level[s[cur].v])
150                         {
151                             break;
152                         }
153                     }
154                     if (cur != -1)
155                     {
156                         que[++q] = cur;
157                         out[u] = s[cur].next;
158                     }
159                     else
160                     {
161                         out[u] = -1;
162                         q--;
163                     }
164                 }
165             }
166         }
167         return ret;
168     }
169 };
170 
171 int m, n;
172 int q[maxn * 10];
173 dinic x, y;
174 int main()
175 {
176     freopen("in.txt", "r", stdin);
177     int cas;
178     cin >> cas;
179     int huijie[maxn];
180     while (cas--)
181     {
182         x.init();
183         scanf("%d%d", &n, &m);
184         for (int i = 0; i < m; i++)
185         {
186             long from, to, cost;
187             scanf("%d %d %d", &from, &to, &cost);
188             x.insert(from, to, cost);
189         }
190         long Start, End;
191         Start = 1; End = n;
192         int tmp = x.max_flow(n, Start, End);//计算一次最大流(最小割)
193 
194 
195         y = x;
196 
197         int ans = 0;
198         int r = 0;
199 
200 
201         for (int j = 2; j < n; j++)//求出汇集---因为bfs找不到一条增广路时,qu中就是原集,剩下来就是汇集,也可以是leve数组便利不到的顶点
202         {
203             if (x.level[j] == 0)
204                 huijie[r++] = j;
205         }
206 
207         for (int i = 0; i <= topset; i++)//枚举两顶点
208         {
209             if (x.que[i] == 1 || x.que[i] == n) continue;
210             for (int j = 0; j < r; j++)
211             {
212                 y = x;
213                 y.insert(x.que[i], huijie[j], inf);//加边
214                 int g = y.max_flow(n, 1, n);//格外的代价
215                 ans = max(ans, g);
216             }
217         }
218         printf("%d
", ans + tmp);
219     }
220     return 0;
221 }
View Code
原文地址:https://www.cnblogs.com/macinchang/p/4694237.html