Loading

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 }

 

posted @ 2016-12-27 16:23  Shadowdsp  阅读(461)  评论(0编辑  收藏  举报