POJ3436
题目链接:http://poj.org/problem?id=3436
题目大意:
一台电脑可以分成P个部分,在生产过程中,半成品电脑有的部分已经完成(记为1),而有的部分还没有完成(记为0)。电脑生产商用N台机器生产电脑,对于放入各台机器的电脑,各自有其要求,即有些部分必须已经完成(记为1),有些部分必须还未完成(记为0),有些部分是否完成无关紧要(记为2),求怎么安排生产线使工厂的总生产效率最高。
解题思路:
最大流问题。
首先是建图。如果某台机器对于放入其中的电脑的要求全为0或者2,那么这台机器就是一个源点,如果某台机器生产出的电脑所有部分都为1,那么这台机器就可以看成一个汇点。这样就有多个源点和多个汇点,那么我们可以设置一个超级源点和超级汇点,超级源点指向每一个源点,每一个汇点指向超级汇点,流量限制为inf。对于每一台机器,为了表示其效率上限,我们将其拆成两个点,表示入口和出口,中间用一条流量限制为机器生存效率的线连接。而对于不同的机器,如果一台机器生产出来的电脑能够送往另一台电脑,那么就将这台机器的出口指向另一台机器的入口,流量限制为inf。建图完成,其他的交给模板。
另一个难点是要printf出最大流经过的路径。那么我们就可以来研究模板跑完以后留下的残量网络。首先有三种路是我们为了方便解决问题而加入的,printf路径的时候必须无视掉:从超级源点流出的路,流入超级汇点的路,由机器入口流到出口的路。那么对于剩下的路,如果路上流量大于0,(或者说残量小于流量限制),那么这条路就是我们这个最大流网络中会经过的,打印出起点、终点和流量即可。
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include <queue> 6 using namespace std; 7 const int inf = 0x7ffffff, maxn = 100 + 5; 8 struct node { 9 int s[12], t[12]; 10 int v; 11 }machine[55]; 12 //模板作者:刘汝佳 13 //************************************************** 14 struct ans { 15 int from, to, num; 16 }ret[maxn]; 17 struct Edge { 18 int from, to, cap, flow; 19 Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f) {} 20 }; 21 vector<int>ans[maxn]; 22 int len = 0, dis[maxn][maxn]; 23 struct Dinic { 24 int n, m, s, t; 25 vector<Edge> edges; 26 vector<int> G[maxn]; 27 bool vis[maxn]; 28 int d[maxn]; 29 int cur[maxn]; 30 31 void init(int n) { 32 this->n = n; 33 for (int i = 0; i < n; i++) G[i].clear(); 34 edges.clear(); 35 } 36 void addedge(int from, int to, int cap) { 37 edges.push_back(Edge(from, to, cap, 0)); 38 edges.push_back(Edge(to, from, 0, 0)); 39 m = edges.size(); 40 G[from].push_back(m - 2); 41 G[to].push_back(m - 1); 42 } 43 bool BFS() { 44 memset(vis, 0, sizeof(vis)); 45 queue<int> Q; 46 Q.push(s); 47 d[s] = 0; 48 vis[s] = 1; 49 while (!Q.empty()) { 50 int x = Q.front(); Q.pop(); 51 for (int i = 0; i < G[x].size(); i++) { 52 Edge &e = edges[G[x][i]]; 53 if (!vis[e.to] && e.cap>e.flow) { 54 vis[e.to] = 1; 55 d[e.to] = d[x] + 1; 56 Q.push(e.to); 57 } 58 } 59 } 60 return vis[t]; 61 } 62 int DFS(int x, int a) { 63 if (x == t || a == 0) return a; 64 int flow = 0, f; 65 for (int &i = cur[x]; i < G[x].size(); i++) { 66 Edge &e = edges[G[x][i]]; 67 if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow)))>0) { 68 e.flow += f; 69 edges[G[x][i] ^ 1].flow -= f; 70 flow += f; 71 a -= f; 72 if (a == 0) break; 73 } 74 } 75 return flow; 76 } 77 int Maxflow(int s, int t) { 78 this->s = s; this->t = t; 79 int flow = 0; 80 while (BFS()) { 81 memset(cur, 0, sizeof(cur)); 82 flow += DFS(s, inf); 83 } 84 return flow; 85 } 86 }; 87 //**************************************************** 88 int main() { 89 // freopen("in.txt","r",stdin); 90 int P, N; 91 Dinic temp; 92 scanf("%d%d", &P, &N); 93 temp.init(2 * N + 2); 94 for (int i = 1; i <= N; i++) { 95 scanf("%d", &machine[i].v); 96 for (int j = 0; j<P; j++) scanf("%d", &machine[i].s[j]); 97 for (int j = 0; j<P; j++) scanf("%d", &machine[i].t[j]); 98 bool sour = true; 99 for (int j = 0; j<P; j++) { 100 if (machine[i].s[j] == 1) { 101 sour = false; 102 break; 103 } 104 } 105 if (sour) temp.addedge(0, i, inf); 106 bool ending = true; 107 for (int j = 0; j<P; j++) { 108 if (machine[i].t[j] != 1) { 109 ending = false; 110 break; 111 } 112 } 113 if (ending) temp.addedge(i + N, 2 * N + 1, inf); 114 temp.addedge(i, i + N, machine[i].v); 115 } 116 for (int i = 1; i <= N; i++) { 117 for (int j = i + 1; j <= N; j++) { 118 bool yes1 = true, yes2 = true; 119 for (int k = 0; k<P; k++) { 120 if (machine[i].t[k]) { 121 if (machine[j].s[k] == 0) yes1 = false; 122 } 123 else { 124 if (machine[j].s[k] == 1) yes1 = false; 125 } 126 if (machine[j].t[k]) { 127 if (machine[i].s[k] == 0) yes2 = false; 128 } 129 else { 130 if (machine[i].s[k] == 1) yes2 = false; 131 } 132 if (!yes1&&!yes2) break; 133 } 134 if (yes1) 135 temp.addedge(i + N, j, inf); 136 if (yes2) 137 temp.addedge(j + N, i, inf); 138 } 139 } 140 printf("%d ", temp.Maxflow(0, 2 * N + 1)); 141 int cnt = 0; 142 143 for (int i = 0; i<temp.edges.size(); i++) { 144 Edge t = temp.edges[i]; 145 int fw = t.flow, f = t.from, tt = t.to; 146 if (fw <= 0 || t.cap == 0 || t.cap != inf || tt>N || f<1) continue; 147 ret[cnt].from = f - N, ret[cnt].to = tt, ret[cnt].num = fw; 148 cnt++; 149 } 150 printf("%d\n", cnt); 151 for (int i = 0; i<cnt; i++) { 152 printf("%d %d %d\n", ret[i].from, ret[i].to, ret[i].num); 153 } 154 return 0; 155 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”