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
", cnt);
151     for (int i = 0; i<cnt; i++) {
152         printf("%d %d %d
", ret[i].from, ret[i].to, ret[i].num);
153     }
154     return 0;
155 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
原文地址:https://www.cnblogs.com/Blogggggg/p/7423972.html