POJ - 3436 ACM Computer Factory (拆点+网络流)
ACM Computer Factory
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 9241 | Accepted: 3412 | Special Judge |
Description
As you know, all the computers used for ACM contests must be identical, so the participants compete on equal terms. That is why all these computers are historically produced at the same factory.
Every ACM computer consists of P parts. When all these parts are present, the computer is ready and can be shipped to one of the numerous ACM contests.
Computer manufacturing is fully automated by using N various machines. Each machine removes some parts from a half-finished computer and adds some new parts (removing of parts is sometimes necessary as the parts cannot be added to a computer in arbitrary order). Each machine is described by its performance (measured in computers per hour), input and output specification.
Input specification describes which parts must be present in a half-finished computer for the machine to be able to operate on it. The specification is a set of P numbers 0, 1 or 2 (one number for each part), where 0 means that corresponding part must not be present, 1 — the part is required, 2 — presence of the part doesn't matter.
Output specification describes the result of the operation, and is a set of P numbers 0 or 1, where 0 means that the part is absent, 1 — the part is present.
The machines are connected by very fast production lines so that delivery time is negligibly small compared to production time.
After many years of operation the overall performance of the ACM Computer Factory became insufficient for satisfying the growing contest needs. That is why ACM directorate decided to upgrade the factory.
As different machines were installed in different time periods, they were often not optimally connected to the existing factory machines. It was noted that the easiest way to upgrade the factory is to rearrange production lines. ACM directorate decided to entrust you with solving this problem.
Input
Input file contains integers P N, then N descriptions of the machines. The description of ith machine is represented as by 2 P + 1 integers Qi Si,1 Si,2...Si,P Di,1 Di,2...Di,P, where Qi specifies performance, Si,j — input specification for part j, Di,k — output specification for part k.
Constraints
1 ≤ P ≤ 10, 1 ≤ N ≤ 50, 1 ≤ Qi ≤ 10000
Output
Output the maximum possible overall performance, then M — number of connections that must be made, then M descriptions of the connections. Each connection between machines A and B must be described by three positive numbersA B W, where W is the number of computers delivered from A to B per hour.
If several solutions exist, output any of them.
Sample Input
Sample input 1 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 input 2 3 5 5 0 0 0 0 1 0 100 0 1 0 1 0 1 3 0 1 0 1 1 0 1 1 0 1 1 1 0 300 1 1 2 1 1 1 Sample input 3 2 2 100 0 0 1 0 200 0 1 1 1
Sample Output
Sample output 1 25 2 1 3 15 2 3 10 Sample output 2 4 5 1 3 3 3 5 3 1 2 1 2 4 1 4 5 1 Sample output 3 0 0
Hint
Bold texts appearing in the sample sections are informative and do not form part of the actual data.
Source
Northeastern Europe 2005, Far-Eastern Subregion
这道题建图很烦,每个物品有m个特性,有n个机器,每个机器都能把特定的物品转换成另一种物品,问最大能处理处理成特性全为1的物品数量为多少,并且把此时必须要建的边写出来。
把机器拆点,中间建一条权值为他们的建造数量的边,把只有(0或2)的机器入口与超级源点建立一条inf的边,把输出全为1的机器出口与超级汇点建立一条inf的边,然后可以互相传送的机器再建边,最后跑一边最大流就好了;
最后要输出必须要建立的边(随意一种输出就好),这样的话我们可以便利所有的边集中,本来建的边的相反边,如果某一条边建的相反边的权值大于0,就说明本身的边的流量已经使用了,且用的流量度就是他的相反边的权值。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn = 100010;
const int maxm = 1000100;
struct spot {
int st[60], en[60], sum;
}spt[maxn];
struct *** {
int u, ne, v, w;
}ed[maxm];
struct answer {
int from, to, len;
}anw[maxm];
int n, m, cnt;
int head[maxn], dis[maxn], cur[maxn];
void init() {
cnt = 0;
memset(head, -1, sizeof(head));
}
void add(int u, int v, int w) {
ed[cnt].w = w; ed[cnt].v = v; ed[cnt].u = u;
ed[cnt].ne = head[u]; head[u] = cnt++;
ed[cnt].w = 0; ed[cnt].v = u; ed[cnt].u = v;
ed[cnt].ne = head[v]; head[v] = cnt++;
}
int bfs(int st, int en) {
queue<int>q;
while (!q.empty())q.pop();
memset(dis, 0, sizeof(dis));
dis[st] = 1;
q.push(st);
while (!q.empty()) {
int u = q.front(); q.pop();
if (u == en)return 1;
for (int s = head[u]; ~s; s = ed[s].ne) {
int v = ed[s].v;
if (dis[v] == 0 && ed[s].w > 0) {
dis[v] = dis[u] + 1; q.push(v);
}
}
}
return dis[en] != 0;
}
int dfs(int st, int en, int flow) {
int res = flow, a;
if (st == en || flow == 0)return flow;
for (int &s = cur[st]; ~s; s = ed[s].ne) {
int v = ed[s].v;
if (dis[v] == dis[st] + 1 && (a = dfs(v, en, min(res, ed[s].w)))) {
ed[s].w -= a;
ed[s ^ 1].w += a;
res -= a;
if (!res)break;
}
}
if (res == flow)dis[st] = 0;
return flow - res;
}
int dinic(int st, int en) {
int ans = 0;
while (bfs(st, en)) {
for (int s = 0; s <= n; s++)
cur[s] = head[s];
ans += dfs(st, en, inf);
}
return ans;
}
int read(int x) {
bool st = 1, en = 1;
for (int s = 1; s <= m; s++) {
if (spt[x].st[s] == 1)st = 0;
if (spt[x].en[s] == 0)en = 0;
}
if (st&&en)return 2;
if (st == 1)return 0;
if (en == 1)return 1;
return -1;
}
int cmp(int a, int b) {
for (int s = 1; s <= m; s++)
if (spt[a].en[s] != spt[b].st[s] && spt[b].st[s] != 2)
return 0;
return 1;
}
int rec(int x) {
if (x % 2)x += 1;
return x >> 1;
return x;
}
int main() {
while (~scanf("%d%d", &m, &n)) {
init();
int end = 2 * n + 1;
for (int s = 1; s <= n; s++) {
scanf("%d", &spt[s].sum);
add(2 * s - 1, 2 * s, spt[s].sum);
for (int w = 1; w <= m; w++)
scanf("%d", &spt[s].st[w]);
for (int w = 1; w <= m; w++)
scanf("%d", &spt[s].en[w]);
}
for (int s = 1; s <= n; s++) {
int t = read(s);
if (t == 1)add(2 * s, end, inf);// cout << s << " " << n + 1 << endl;
if (t == 0)add(0, 2 * s - 1, inf);// cout << 0 << " " << s << endl;
if (t == 2)add(2 * s, end, inf), add(0, 2 * s - 1, inf);
}
for(int s = 1; s < n ; s++)
for (int w = s + 1; w <= n; w++) {
if (cmp(s, w))add(2 * s, 2 * w - 1, inf);// cout << s << " " << w << endl;
if (cmp(w, s))add(2 * w, 2 * s - 1, inf);// cout << w << " " << s << endl;
}
n = end;
int ans = dinic(0, end), ecnt = 0;
for (int s = 0; s < cnt; s += 2) {
if (ed[s ^ 1].w > 0 && ed[s].u != 0 && ed[s].v != end&&rec(ed[s].u) != rec(ed[s].v))
anw[ecnt].from = rec(ed[s].u), anw[ecnt].to = rec(ed[s].v), anw[ecnt++].len = ed[s ^ 1].w;
}
cout << ans << " " << ecnt << endl;
for (int s = 0; s < ecnt; s++)
printf("%d %d %d\n",anw[s].from,anw[s].to,anw[s].len);
}
}