标签:turn min copy for span 网络流 mem 机器 strong
题意:
电脑公司生产电脑有N个机器,每个机器单位时间产量为Qi。 电脑由P个部件组成,每个机器工作时只能把有某些部件的半成品电脑(或什么都没有的空电脑)变成有另一些部件的半成品电脑或完整电脑(也可能移除某些部件)。求电脑公司的单位时间最大产量,以及哪些机器有协作关系,即一台机器把它的产品交给哪些机器加工。
Sample input
3 4
15 0 0 0 0 1 0
10 0 0 0 0 1 1
30 0 1 2 1 1 1
3 0 2 1 1 1 1
Sample output
25 2
1 3 15
2 3 10
输入:电脑由3个部件组成,共有4台机器,1号机器产量15, 能给空电脑加上2号部件,2号 机器能给空电脑加上2号部件和3号部件, 3号机器能把有1个2号部件和3号部件有无均可的电脑变成成品(每种部件各有一个)
输出:单位时间最大产量25,有两台机器有协作关系,
1号机器单位时间内要将15个电脑给3号机器加工
2号机器单位时间内要将10个电脑给3号机器加工
思路:
网络流模型:
1) 添加一个原点S,S提供最初的原料 00000...
2) 添加一个汇点T, T接受最终的产品 11111...
3) 将每个机器拆成两个点: 编号为i的接收节点,和编号为i+n的产出节点(n是机器数目),前者用于接收原料,后者用于提供加工后的半成品或成品。这两个点之间要连一条边,容量为单位时间产量Qi
4) S 连边到所有接收 "0000..." 或 "若干个0及若干个2" 的机器,容量为无穷大
5) 产出节点连边到能接受其产品的接收节点,容量无穷大
6) 能产出成品的节点,连边到T,容量无穷大。
7) 求S到T的最大流
实现:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using namespace std; 6 7 const int INF = 0x3f3f3f3f; 8 9 int g[105][15], p, n, q[55]; 10 int G[105][105], G_copy[105][105], layer[105], vis[105]; 11 12 struct node 13 { 14 int x, y, c; 15 }; 16 17 bool countLayer(int s, int e) 18 { 19 layer[s] = 0; 20 queue<int> q; 21 q.push(s); 22 memset(vis, 0, sizeof(vis)); 23 vis[s] = true; 24 while (!q.empty()) 25 { 26 int tmp = q.front(); 27 q.pop(); 28 for (int i = 1; i <= e; i++) 29 { 30 if (G[tmp][i] && !vis[i]) 31 { 32 layer[i] = layer[tmp] + 1; 33 if (i == e) 34 { 35 return true; 36 } 37 vis[i] = true; 38 q.push(i); 39 } 40 } 41 } 42 return false; 43 } 44 45 int dinic(int s, int e) 46 { 47 int flow = 0; 48 deque<int> q; 49 while (countLayer(s, e)) 50 { 51 memset(vis, 0, sizeof(vis)); 52 vis[s] = true; 53 q.push_back(s); 54 while (!q.empty()) 55 { 56 int tmp = q.back(); 57 if (tmp == e) 58 { 59 int minn = INF; 60 int min_index = 0; 61 for (int i = 1; i < q.size(); i++) 62 { 63 if (G[q[i - 1]][q[i]] && G[q[i - 1]][q[i]] < minn) 64 { 65 minn = G[q[i - 1]][q[i]]; 66 min_index = i - 1; 67 } 68 } 69 for (int i = 1; i < q.size(); i++) 70 { 71 G[q[i - 1]][q[i]] -= minn; 72 G[q[i]][q[i - 1]] += minn; 73 } 74 while (q.size() && q.back() != min_index) 75 { 76 vis[q.back()] = false; 77 q.pop_back(); 78 } 79 flow += minn; 80 } 81 else 82 { 83 bool flag = false; 84 for (int i = 1; i <= e; i++) 85 { 86 if (G[tmp][i] && !vis[i] && layer[i] == layer[tmp] + 1) 87 { 88 vis[i] = true; 89 q.push_back(i); 90 flag = true; 91 break; 92 } 93 } 94 if (!flag && q.size()) 95 { 96 q.pop_back(); 97 } 98 } 99 } 100 } 101 return flow; 102 } 103 104 int main() 105 { 106 while (cin >> p >> n) 107 { 108 for (int i = 0; i < n; i++) 109 { 110 cin >> q[i]; 111 for (int j = 0; j < p; j++) 112 { 113 cin >> g[i][j]; 114 } 115 for (int j = 0; j < p; j++) 116 { 117 cin >> g[i + n][j]; 118 } 119 } 120 memset(G, 0, sizeof(G)); 121 for (int i = 2; i < n + 2; i++) 122 { 123 G[i][i + n] = q[i - 2]; 124 } 125 for (int i = 2; i < n + 2; i++) 126 { 127 bool flag = true; 128 for (int j = 0; j < p; j++) 129 { 130 if (g[i - 2][j] != 0 && g[i - 2][j] != 2) 131 { 132 flag = false; 133 break; 134 } 135 } 136 if (flag) 137 { 138 G[1][i] = INF; 139 } 140 } 141 for (int i = n + 2; i < 2 * n + 2; i++) 142 { 143 bool flag = true; 144 for (int j = 0; j < p; j++) 145 { 146 if (g[i - 2][j] != 1) 147 { 148 flag = false; 149 break; 150 } 151 } 152 if (flag) 153 { 154 G[i][2 * n + 2] = INF; 155 } 156 } 157 for (int i = n + 2; i < 2 * n + 2; i++) 158 { 159 for (int j = 2; j < n + 2; j++) 160 { 161 bool flag = true; 162 for (int k = 0; k < p; k++) 163 { 164 if (!(g[i - 2][k] == g[j - 2][k] || g[j - 2][k] == 2)) 165 { 166 flag = false; 167 break; 168 } 169 } 170 if (flag) 171 { 172 G[i][j] = INF; 173 } 174 } 175 } 176 for (int i = 1; i <= 2 * n + 2; i++) 177 { 178 for (int j = 1; j <= 2 * n + 2; j++) 179 { 180 G_copy[i][j] = G[i][j]; 181 } 182 } 183 cout << dinic(1, 2 * n + 2) << " "; 184 int cnt = 0; 185 vector<node> v; 186 for (int i = n + 2; i < 2 * n + 2; i++) 187 { 188 for (int j = 2; j < n + 2; j++) 189 { 190 if (i - n != j && G[i][j] != G_copy[i][j]) 191 { 192 cnt++; 193 node tmp; 194 tmp.x = i - n - 1; 195 tmp.y = j - 1; 196 tmp.c = G_copy[i][j] - G[i][j]; 197 v.push_back(tmp); 198 } 199 } 200 } 201 cout << cnt << endl; 202 for (int i = 0; i < v.size(); i++) 203 { 204 cout << v[i].x << " " << v[i].y << " " << v[i].c << endl; 205 } 206 } 207 return 0; 208 }
标签:turn min copy for span 网络流 mem 机器 strong
原文地址:http://www.cnblogs.com/wangyiming/p/6357709.html