HDU 4280:Island Transport(ISAP模板题)
http://acm.hdu.edu.cn/showproblem.php?pid=4280
题意:在最西边的点走到最东边的点最大容量。
思路:ISAP模板题,Dinic过不了。
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include <queue> 8 #include <vector> 9 #include <map> 10 #include <set> 11 using namespace std; 12 #define INF 0x3f3f3f3f 13 #define N 100010 14 typedef long long LL; 15 struct Edge { 16 int u, v; 17 LL cap; 18 Edge () {} 19 Edge (int u, int v, LL cap) : u(u), v(v), cap(cap) {} 20 }edge[N*4]; 21 vector<int> G[N]; 22 int dis[N], cur[N], num[N], pre[N], tot, S, T; 23 24 void Add(int u, int v, int cap) { 25 edge[tot] = Edge(u, v, cap); 26 G[u].push_back(tot++); 27 edge[tot] = Edge(v, u, cap); 28 G[v].push_back(tot++); 29 } 30 31 int BFS() { // 逆向BFS 32 memset(dis, -1, sizeof(dis)); 33 queue<int> que; que.push(T); 34 dis[T] = 0; 35 while(!que.empty()) { 36 int u = que.front(); que.pop(); 37 for(int i = 0; i < G[u].size(); i++) { 38 Edge &e = edge[G[u][i]]; 39 if(dis[e.v] == -1) { 40 dis[e.v] = dis[u] + 1; 41 que.push(e.v); 42 } 43 } 44 } 45 return ~dis[S]; 46 } 47 48 int DFS() { // 通过pre数组回溯更新流量 49 int u = T; int flow = INF; 50 while(u != S) { 51 Edge &e = edge[pre[u]]; 52 if(e.cap < flow) flow = e.cap; 53 u = e.u; 54 } u = T; 55 while(u != S) { 56 Edge& e1 = edge[pre[u]]; 57 Edge& e2 = edge[pre[u]^1]; 58 e1.cap -= flow; e2.cap += flow; 59 u = e1.u; 60 } 61 return flow; 62 } 63 64 int ISAP(int n) { 65 if(!BFS()) return 0; // 从汇点到源点逆向BFS初始化dis数组 66 memset(num, 0, sizeof(num)); 67 memset(cur, 0, sizeof(cur)); // 当前弧优化 68 for(int i = 1; i <= n; i++) 69 if(~dis[i]) num[dis[i]]++; // 当前距离为dis[i]的结点数 70 int ans = 0, u = S; 71 while(dis[S] < n) { 72 if(u == T) ans += DFS(), u = S; // 回溯之前的结点并把更新流量 73 int flag = 0; 74 for(int i = 0; i < G[u].size(); i++) { 75 Edge &e = edge[G[u][i]]; 76 if(dis[e.v] + 1 == dis[u] && e.cap > 0) { // 可以增广 77 pre[e.v] = G[u][i]; cur[u] = i; 78 flag = 1; u = e.v; 79 break; 80 } 81 } 82 if(!flag) { // 不能增广,retreat 83 if(--num[dis[u]] == 0) break; // gap优化 84 int md = n; 85 for(int i = 0; i < G[u].size(); i++) { 86 Edge &e = edge[G[u][i]]; 87 if(e.cap > 0 && dis[e.v] < md) { 88 md = dis[e.v]; cur[u] = i; 89 } 90 } 91 num[dis[u] = md + 1]++; 92 if(u != S) u = edge[pre[u]].u; 93 } 94 } 95 return ans; 96 } 97 98 int main() { 99 int t; 100 scanf("%d", &t); 101 while(t--) { 102 int n, m; 103 scanf("%d%d", &n, &m); 104 tot = 0; for(int i = 0; i <= n; i++) G[i].clear(); 105 int u, v, c, west = 100000000, east = -10000000; 106 for(int i = 1; i <= n; i++) { 107 scanf("%d%d", &u, &v); 108 if(west > u) west = u, S = i; 109 if(east < u) east = u, T = i; 110 } 111 for(int i = 1; i <= m; i++) { 112 scanf("%d%d%d", &u, &v, &c); 113 Add(u, v, c); // 无向图的话反向边的cap也是c 114 } 115 printf("%d\n", ISAP(n)); 116 } 117 return 0; 118 }