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\n", 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\n", 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\n", 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\n", i, j, mp[i][j]); 127 } 128 return 0; 129 }