POJ 3436:ACM Computer Factory(最大流记录路径)

http://poj.org/problem?id=3436

题意:题意很难懂。给出P N。接下来N行代表N个机器,每一行有2*P+1个数字

第一个数代表容量,第2~P+1个数代表输入,第P+2到2*P+1是代表输出

输入有三种情况,0,1,2.输出有0,1两种情况
输入0代表不能有这个接口,1代表必须要有这个接口,2代表这个接口可有可无。
输出0代表有这个接口,1代表没有这个接口。大概输出就是像插头,输入像插座,只有接口吻合才可以相连。

思路:比较简单的最大流,主要是理解题意很难,把每台机器拆成输入和输出两个点,之间的流量就是第一个数那个流量,然后把符合题意的输入和超级源点相连,把符合题意的输出和超级汇点相连,把符合题意的机器之间的输入输出相连,流量都是INF,用ISAP找到增广路更新的时候,可以顺便记录路径。也可以最后和初始流量比较,如果减少了就说明有流量经过。可是ISAP模板错了导致一直WA了好久,以为是思路错了,用Dinic做过了,这里重新找了份鸟神的模板Orz。

Dinic:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <queue>
  5 #include <vector>
  6 using namespace std;
  7 #define N 400
  8 const int INF = 0x3f3f3f3f;
  9 
 10 struct Edge {
 11     int u, v, cap, init;
 12     Edge () {}
 13     Edge (int u, int v, int cap, int init) : u(u), v(v), cap(cap), init(init) {}
 14 }edge[N];
 15 vector<int> G[N];
 16 int cur[N], dis[N], gap[N], pre[N], tot, S, T;
 17 int mp[N][N], info[N][N];
 18 
 19 void Add(int u, int v, int cap) {
 20     edge[tot] = Edge(u, v, cap, cap);
 21     G[u].push_back(tot++);
 22     edge[tot] = Edge(v, u, 0, 0);
 23     G[v].push_back(tot++);
 24 }
 25 
 26 int BFS() {
 27     queue<int> que;
 28     while(!que.empty()) que.pop();
 29     memset(dis, INF, sizeof(dis));
 30     dis[S] = 0; que.push(S);
 31     while(!que.empty()) {
 32         int u = que.front(); que.pop();
 33         for(int i = 0; i < G[u].size(); i++) {
 34             Edge& e = edge[G[u][i]];
 35             if(dis[e.v] == INF && e.cap > 0) {
 36                 dis[e.v] = dis[u] + 1;
 37                 que.push(e.v);
 38             }
 39         }
 40     }
 41     return dis[T] < INF;
 42 }
 43 
 44 int DFS(int u, int maxflow) {
 45     if(u == T) return maxflow;
 46     for(int i = cur[u]; i < G[u].size(); i++) {
 47         cur[u] = i; Edge& e = edge[G[u][i]];
 48         if(dis[e.v] == dis[u] + 1 && e.cap > 0) {
 49             int flow = DFS(e.v, min(maxflow, e.cap));
 50             if(flow > 0) {
 51                 e.cap -= flow;
 52                 edge[G[u][i] ^ 1].cap += flow;
 53                 return flow;
 54             }
 55         }
 56     }
 57     return 0;
 58 }
 59 
 60 int Dinic() {
 61     int ans = 0;
 62     while(BFS()) {
 63         memset(cur, 0, sizeof(cur));
 64         int flow;
 65         while(flow = DFS(S, INF)) ans += flow;
 66     }
 67     return ans;
 68 }
 69 
 70 int main() {
 71     int P, n;
 72     while(~scanf("%d%d", &P, &n)) {
 73         tot = 0; S = 0, T = 2 * n + 1;
 74         for(int i = S; i <= T; i++) G[i].clear();
 75         memset(mp, 0, sizeof(mp));
 76         for(int i = 1; i <= n; i++) {
 77             scanf("%d", &info[i][0]);
 78             for(int j = 1; j <= P; j++)
 79                 scanf("%d", &info[i][j]);
 80             for(int j = 1; j <= P; j++)
 81                 scanf("%d", &info[i][j+P]);
 82         }
 83         for(int i = 1; i <= n; i++) {
 84             Add(i, i + n, info[i][0]);
 85             int fs = 1, ft = 1;
 86             for(int j = 1; j <= P; j++) {
 87                 if(info[i][j] == 1) fs = 0;
 88                 if(info[i][j+P] == 0) ft = 0;
 89             }
 90             if(fs) Add(S, i, INF);
 91             if(ft) Add(i + n, T, INF);
 92             for(int j = 1; j <= n; j++) {
 93                 if(i == j) continue;
 94                 fs = 1;
 95                 for(int k = 1; k <= P; k++)
 96                     if(info[i][k+P] != info[j][k] && info[j][k] != 2)
 97                         fs = 0;
 98                 if(fs) Add(i + n, j, INF);
 99             }
100         }
101         int ans = Dinic(), cnt = 0;
102         for(int u = n + 1; u <= 2 * n; u++) {
103             for(int j = 0; j < G[u].size(); j++) {
104                 Edge& e = edge[G[u][j]];
105                 if(e.v <= n && e.v > 0 && e.cap < e.init) mp[u-n][e.v] += e.init - e.cap;
106             }
107         }
108         for(int i = 1; i <= n; i++) {
109             for(int j = 1; j <= n; j++) {
110                 if(mp[i][j]) cnt++;
111             }
112         }
113         printf("%d %d
", ans, cnt);
114         for(int i = 1; i <= n; i++) {
115             for(int j = 1; j <= n; j++) {
116                 if(mp[i][j]) printf("%d %d %d
", i, j, mp[i][j]);
117             }
118         }
119     }
120     return 0;
121 }

ISAP:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <queue>
  5 #include <vector>
  6 using namespace std;
  7 #define N 400
  8 const int INF = 0x3f3f3f3f;
  9 
 10 struct Edge {
 11     int v, nxt, cap, init;
 12 }edge[N];
 13 int cur[N], dis[N], gap[N], pre[N], head[N], tot, S, T;
 14 int mp[N][N], info[N][N];
 15 
 16 void Add(int u, int v, int cap) {
 17     edge[tot].nxt = head[u]; edge[tot].v = v; edge[tot].cap = cap; edge[tot].init = cap; head[u] = tot++;
 18     edge[tot].nxt = head[v]; edge[tot].v = u; edge[tot].cap = 0; edge[tot].init = 0; head[v] = tot++;
 19 }
 20 
 21 int BFS() {
 22     queue<int> que;
 23     while(!que.empty()) que.pop();
 24     memset(dis, -1, sizeof(dis));
 25     memset(gap, 0, sizeof(gap));
 26     que.push(T); dis[T] = 0;
 27     gap[0] = 1;
 28     while(!que.empty()) {
 29         int u = que.front(); que.pop();
 30         for(int i = head[u]; ~i; i = edge[i].nxt) {
 31             int v = edge[i].v;
 32             if(~dis[v]) continue;
 33             dis[v] = dis[u] + 1;
 34             gap[dis[v]]++;
 35             que.push(v);
 36         }
 37     }
 38     return ~dis[S];
 39 }
 40 
 41 int ISAP(int n, int m) { // n = T + 1 !!!
 42     memcpy(cur, head, sizeof(cur));
 43     int ans = 0, i, u = pre[S] = S;
 44     while(dis[S] < n) {
 45         if(u == T) {
 46             int flow = INF, index = S;
 47             for(i = S; i != T; i = edge[cur[i]].v) {
 48                 if(flow > edge[cur[i]].cap) {
 49                     flow = edge[cur[i]].cap; index = i;
 50                 }
 51             }
 52             for(i = S; i != T; i = edge[cur[i]].v) {
 53                 edge[cur[i]].cap -= flow; edge[cur[i]^1].cap += flow;
 54                 int v = edge[cur[i]].v;
 55                 if(i > m && v > S && v <= m) {
 56                     mp[i-m][v] += flow;
 57                 }
 58             }
 59             ans += flow;
 60             u = index;
 61         }
 62         for(i = cur[u]; ~i; i = edge[i].nxt)
 63             if(edge[i].cap > 0 && dis[edge[i].v] + 1 == dis[u])
 64                 break;
 65         if(~i) {
 66             cur[u] = i;
 67             pre[edge[i].v] = u;
 68             u = edge[i].v;
 69         } else {
 70             if(--gap[dis[u]] == 0) break;
 71             int md = n;
 72             for(i = head[u]; ~i; i = edge[i].nxt) {
 73                 if(dis[edge[i].v] < md && edge[i].cap > 0) {
 74                     md = dis[edge[i].v]; cur[u] = i;
 75                 }
 76             }
 77             ++gap[dis[u] = md + 1];
 78             u = pre[u];
 79         }
 80     }
 81     return ans;
 82 }
 83 
 84 int main() {
 85     int n, P;
 86     while(~scanf("%d%d", &P ,&n)) {
 87         memset(head, -1, sizeof(head));
 88         memset(mp, 0, sizeof(mp));
 89         tot = 0; S = 0; T = 2 * n + 1;
 90         for(int i = 1; i <= n; i++) {
 91             scanf("%d", &info[i][0]);
 92             for(int j = 1; j <= P; j++)
 93                 scanf("%d", &info[i][j]);
 94             for(int j = 1; j <= P; j++)
 95                 scanf("%d", &info[i][j+P]);
 96         }
 97         for(int i = 1; i <= n; i++) {
 98             Add(i, i + n, info[i][0]);
 99             int fs = 1, ft = 1;
100             for(int j = 1; j <= P; j++) {
101                 if(info[i][j+P] == 0) ft = 0;
102                 if(info[i][j] == 1) fs = 0;
103             }
104             if(fs) Add(S, i, INF);
105             if(ft) Add(i + n, T, INF);
106             for(int j = 1; j <= n; j++) {
107                 fs = 1;
108                 for(int k = 1; k <= P; k++)
109                     if(info[j][k] != 2 && info[j][k] != info[i][k+P]) fs = 0;
110                 if(fs) Add(i + n, j, INF);
111             }
112         }
113         int ans = ISAP(T + 1, n), cnt = 0;
114 //        for(int i = n + 1; i <= 2 * n; i++) {
115 //            for(int j = head[i]; ~j; j = edge[j].nxt) {
116 //                int v = edge[j].v;
117 //                if(v > 0 && v <= n && edge[j].cap < edge[j].init) mp[i-n][v] += edge[j].init - edge[j].cap;
118 //            }
119 //        }
120         for(int i = 1; i <= n; i++)
121             for(int j = 1; j <= n; j++)
122                 if(mp[i][j]) cnt++;
123         printf("%d %d
", ans, cnt);
124         for(int i = 1; i <= n; i++)
125             for(int j = 1; j <= n; j++)
126                 if(mp[i][j]) printf("%d %d %d
", i, j, mp[i][j]);
127     }
128     return 0;
129 }
原文地址:https://www.cnblogs.com/fightfordream/p/6233838.html