HDU 2435 There is a war Dinic 最小割
题意是有n座城市,n号城市不想让1号城市可达n号,每条道路有一条毁坏的代价,1号还可以修一条不能毁坏的道路,求n号城市所需的最小代价最大是多少。
毁坏的最小代价就直接求一遍最大流,就是最小割了。而可以修一条不能毁坏的路,需要枚举的这些边就是源集中的点到汇集中的点,我之前的做法是直接找出所有的割边,再枚举每一条割边,在这两个点上加一个流量为无穷大的边再去求最大流,实际上这样连样例的第二个数据都过不了,因为图不保证是连通的,那就有一些源集中的点和汇集中的点本来就不联通,就不存在这样的割边了。发现这个错误后,我就在没有联通的所有边中加了一条cap为0的边,想弥补上面的bug,但是这样的话超时了。奇怪的是,我没有加那些cap为0的点的时候也是超时而不是wa。
所以就找出所有的源点,找出所有的汇点,去除1和n后枚举这些边在原来的基础上去跑最大流,得出来的意义就是如果修的是这条路,所需要的额外的代价。
我自己的代码不知道为什么过不了,可能是模板的问题?
贴两个代码吧,前面是自己的,后面是别人的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n", ans + tmp); 219 } 220 return 0; 221 }