解题报告 之 POJ3463 ACM Computer Factory

解题报告 之 POJ3463 ACM Computer Factory

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 PN, then N descriptions of the machines. The description of ith machine is represented as by 2 P + 1 integers QiSi,1Si,2...Si,PDi,1Di,2...Di,P,
where Qi specifies performance, Si,j — input specification for part jDi,k — output specification for part k.

Constraints

1 ≤ P ≤ 10, 1 ≤ ≤ 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 numbers ABW,
where W is the number of computers delivered from A to B per hour.

If several solutions exist, output any of them.

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
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
2 2
100  0 0  1 0
200  0 1  1 1

Sample Output

25 2
1 3 15
2 3 10
4 5
1 3 3
3 5 3
1 2 1
2 4 1
4 5 1
0 0

题目大意:现在你要组装电脑,一台电脑由p个组件构成,现在有n台组装机。每一台组装机接收一定格式的半成品(输入中会给出组装机i的输入需要满足的格式,对于组件j,1表示该组件要有,0表示该组件必须没有,2表示该组件可有可无),输出组装后另一种格式的半成品(或成品,即全部为1)。每台组装机有一个组装能力cap。问你最多能组装多少台电脑?并且每台组装机相互之间是传递了多少半成品。

分析:凭借着我高超的阅读理解能力以及强大的网络流功底(怎么我自己都不相信?!)。一看就明显是最大流,而且思路都很清晰啊,拆点,超级源点汇点,以及残余网络流量判定。居然在一个细节被坑了三个小时。。

好吧说正题:怎么构造最大流呢?首先所有组装机拆点,负载为组装机的cap,以此限制流量。然后如果该组装机要求的输入格式为全0(即接受还未开始组装的电脑),那么超级源点与该组装机相连,负载为INF;如果组装机输出格式为全1,则该组装机与超级汇点相连,负载为INF。然后遍历任意两台组装机i、j,如果out[i]满足in[j]
---> 即第i台组装机的输出格式满足第j台组装机的输入格式,那么就连一条边,负载为INF。至此跑最大流看看是多少即可。对于残余网络,你去扫描所有从组装机入点(拆点后的入点)所连接的所有边,筛选出既不是连接des,也不是连接拆点的出点的那些边,输出即可。

如果看到这里你都觉得没问题的话:那么你就跟我犯了一样的错误。那么错误在哪呢? 源点与组装机连接的条件并不要求组装机输入格式为全0,还可以有2!(仔细想想)。所以判断的时候应该统一用match函数(见代码)而非使用in[i]==string(p,‘0‘)这种炫技作死的手法(p表示零件数)。
BTW,似乎也有不拆点的方法,但是数据量很小所以拆不拆其实差不多。

上代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
using namespace std;

const int MAXM = 251000;
const int MAXN = 510;
const int INF = 0x3f3f3f3f;

struct Edge
{
	int from, to, cap, next, oricap;
};

Edge edge[MAXM];
int output[MAXM];
int level[MAXN];
int head[MAXN];
int cap[MAXN];
string in[MAXN];
string out[MAXN];
int src, des, cnt;

bool match( string out, string in, int p )
{
	for (int i = 0; i < p; i++)
	if (out[i] + in[i] == '0' + '1')
		return false;
	return true;
}

void addedge( int from, int to, int cap )
{
	edge[cnt].from = from;
	edge[cnt].to = to;
	edge[cnt].cap = edge[cnt].oricap = cap;
	edge[cnt].next = head[from];
	head[from] = cnt++;

	swap( from, to );

	edge[cnt].from = from;
	edge[cnt].to = to;
	edge[cnt].cap = edge[cnt].oricap = 0;
	edge[cnt].next = head[from];
	head[from] = cnt++;
}

int bfs( )
{
	memset( level, -1, sizeof level );
	queue<int>q;
	while (!q.empty( ))
		q.pop( );

	level[src] = 0;
	q.push( src );

	while (!q.empty( ))
	{
		int u = q.front( );
		q.pop( );

		for (int i = head[u]; i != -1; i = edge[i].next)
		{
			int v = edge[i].to;
			if (edge[i].cap > 0 && level[v] == -1)
			{
				level[v] = level[u] + 1;
				q.push( v );
			}
		}
	}
	return level[des] != -1;
}

int dfs( int u, int f )
{
	if (u == des) return f;
	int tem;
	for (int i = head[u]; i != -1; i = edge[i].next)
	{
		int v = edge[i].to;
		if (edge[i].cap>0 && level[v] == level[u] + 1)
		{
			tem = dfs( v, min( f, edge[i].cap ) );
			if (tem > 0)
			{
				edge[i].cap -= tem;
				edge[i ^ 1].cap += tem;
				return tem;
			}
		}
	}
	level[u] = -1;
	return 0;
}

int Dinic( )
{
	int ans = 0, tem;

	while (bfs( ))
	{
		while ((tem = dfs( src, INF )) > 0)
		{
			ans += tem;
		}
	}
	return ans;
}

int main( )
{
	int p, n;
	src = 0;
	des = 505;
	while (cin >> p >> n)
	{
		memset( head, -1, sizeof head );
		cnt = 0;
		for (int i = 1; i <= n; i++)
		{
			cin >> cap[i];
			in[i] = out[i] = "";
			char ch;
			for (int j = 1; j <= p; j++)
			{
				cin >> ch;
				in[i] += ch;
			}
			for (int j = 1; j <= p; j++)
			{
				cin >> ch;
				out[i] += ch;
			}
		}

		for (int i = 1; i <= n; i++)
		{
			addedge( i, i + 50, cap[i] );

			if (match(in[i],string(p,'0'),p))
				addedge( src, i, INF );

			if (match(out[i],string(p,'1'),p))
				addedge( i + 50, des, INF );

			for (int j = 1; j <= n; j++)
			if (match( out[i], in[j], p ))
				addedge( i + 50, j, INF );
		}

		int ans = Dinic( );
		int num = 0;

		for (int i = 1 + 50; i <= n + 50; i++)
		{
			for (int j = head[i]; j != -1; j = edge[j].next)
			{
				if (edge[j].from == edge[j].to + 50 || edge[j].to == des) continue;
				if (edge[j].oricap > edge[j].cap) output[num++] = j;
			}
		}

		printf( "%d %d\n", ans, num );

		for (int i = 0; i < num; i++)
		{
			printf( "%d %d %d\n", edge[output[i]].from - 50, edge[output[i]].to, edge[output[i]].oricap - edge[output[i]].cap );
		}
	}
	return 0;
}

好了我要去赶MATLAB的作业了。。尼玛这个细节我终身难忘。再次证明了构图是最大流最难的部分!!

时间: 2024-10-12 03:23:18

解题报告 之 POJ3463 ACM Computer Factory的相关文章

Poj 3436 ACM Computer Factory (最大流)

题目链接: Poj 3436 ACM Computer Factory 题目描述: n个工厂,每个工厂能把电脑s态转化为d态,每个电脑有p个部件,问整个工厂系统在每个小时内最多能加工多少台电脑? 解题思路: 因为需要输出流水线要经过的工厂路径,如果要用电脑状态当做节点的话,就GG了.所以建图的时候要把工厂当做节点.对于节点i,能生产si电脑的节点可以进入节点i,能转化ei电脑的节点可以由i节点进入.要注意对于每一个节点要进行拆点,防止流量发生错误. 1 #include <queue> 2 #

POJ3436 ACM Computer Factory 【最大流】

ACM Computer Factory Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5412   Accepted: 1863   Special Judge Description As you know, all the computers used for ACM contests must be identical, so the participants compete on equal terms. Th

POJ 3436 ACM Computer Factory(网络最大流)

http://poj.org/problem?id=3436 ACM Computer Factory Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5286   Accepted: 1813   Special Judge Description As you know, all the computers used for ACM contests must be identical, so the particip

poj3436 ACM Computer Factory, 最大流,输出路径

POJ 3436 ACM Computer Factory 电脑公司生产电脑有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

ACM Computer Factory(dinic)

ACM Computer Factory Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5596   Accepted: 1922   Special Judge Description As you know, all the computers used for ACM contests must be identical, so the participants compete on equal terms. Th

POJ 3436 ACM Computer Factory (最大流 + 输出路径)

POJ 3436 ACM Computer Factory 链接:http://poj.org/problem?id=3436 题意:每台电脑有P部分,可以通过不同的机器来进行加工.有N台机器,每台机器用2 P +1 个整数来描述:Qi  Si,1  Si,2 ...  Si,p  Di,1  Di,2. ..  Di,p,其中Qi 指定了机器的性能,表示每小时加工的电脑数量.Si,j 为第j 部分的输入规格,0表示该部分不能被加工过,1表示该部分必须被加工过,2表示都可以.Di,k 为第k 部

POJ-3436 ACM Computer Factory (最大流[Ford-Fulkerson])

ACM Computer Factory http://poj.org/problem?id=3436 Time Limit: 1000MS   Memory Limit: 65536K         Special Judge Description As you know, all the computers used for ACM contests must be identical, so the participants compete on equal terms. That i

POJ-3436 ACM Computer Factory(网络流EK)

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

18.11.23 POJ 3436 ACM Computer Factory(dinic)

描述 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 the