zoukankan      html  css  js  c++  java
  • POJ3436-ACM Computer Factory(最大流)

    题意:每台ACM电脑都由P个零件组成。当一台电脑的每个零件都有的时候,那么这台电脑就可以拿来参赛了。电脑工厂准备用N台机器来生成这些电脑,每台电脑会接受一些零件不足的半成品,并生产出一台电脑,这台电脑可能是完成品或者是半成品。每台机器的效率由它的每单位时间生成的电脑数量,输入规格和输出规格所决定。规格由P个整数所描述,0表示这个零件不需要,1表示这个零件需要,2表示这个零件可有可无。输出规格也同样。每台机器由一些生产线相连,ACM协会决定重新摆放生产线来使得每小时生成的电脑数量最多。

    输入:输入由P,N组成,N表示有N台机器,接下来是N行机器的规格描述,每行有2 * p + 1个整数,(Qi,Si_1,Si_2...Si_p,Di_1,Di_2...Di_p),表示单位时间内生成的电脑数量,输入规格和输出规格。对于一台机器的输入规格,只能和另一台机器的输出规格相匹配,它们才能由生产线相连。

    输出:输出最大的单位时间内的生产数量。然后输出M,表示相连的方案数,并输出具体的方案。

    分析:最大流问题,我采用的是邻接表的方式建图,考虑建图方式,首先的一个是容量限制,每台机器具有一个生成效率,因此需要拆成两个点,输出点为(i + n),输入点为(i),然后连一条(容量为Q)的边。1.每台机器的输出点向符和的输入点的机器连一条容量为inf的边。2.建立一个超级汇点,从汇点向每台机器的输入规格为("000..."或者"若干个0和若干个2")的机器连一条容量为(inf)的边3.建立一个超级源点,输出规模为全1的机器向它连一套容量为"inf"的边。然后求从起点到终点的最大流。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 55;
    const int M = N * N + 4 * N;
    const int inf = 1 << 29;
    
    struct Node
    {
    	int in[15], out[15], q;
    }ma[N];
    
    int h[4 * N], e[2 * M], ne[2 * M], idx;
    int w[2 * M];
    
    int incf[4 * N], pre[4 * N];
    bool st[4 * N];
    
    //p个零件,n台机器
    int p, n;
    int s, t, maxflow;
    
    void add(int a, int b, int c)
    {
    	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
    	e[idx] = a, w[idx] = 0, ne[idx] = h[b], h[b] = idx++;
    }
    
    bool bfs()
    {
    	memset(st, 0, sizeof st);
    	stack<int> q;
    	q.push(s);
    	st[s] = true;
    	incf[s] = inf;
    
    	while (q.size())
    	{
    		int u = q.top();
    		q.pop();
    
    		for (int i = h[u]; i != -1; i = ne[i])
    		{
    			if (w[i])
    			{
    				int j = e[i];
    				if (st[j]) continue;
    				incf[j] = min(incf[u], w[i]);
    				pre[j] = i;
    				q.push(j), st[j] = true;
    				if (j == t) return true;
    			}
    		}
    	}
    	return false;
    }
    
    void update()
    {
    	int u = t;
    	while (u != s)
    	{
    		int i = pre[u];
    		w[i] -= incf[t];
    		w[i ^ 1] += incf[t];
    		u = e[i ^ 1];
    	}
    	maxflow += incf[t];
    }
    
    struct re
    {
    	int a, b, c;
    	re(int a, int b, int c):a(a), b(b), c(c){}
    };
    
    int main()
    {
    	scanf("%d%d", &p, &n);
    	memset(h, -1, sizeof h);
    	idx = 0, maxflow = 0;
    
    	for (int i = 1; i <= n; ++i)
    	{
    		scanf("%d", &ma[i].q);
    		for (int j = 1; j <= p; ++j) scanf("%d", &ma[i].in[j]);
    		for (int j = 1; j <= p; ++j) scanf("%d", &ma[i].out[j]);
    	}
    
    	s = 0, t = 2 * n + 1;
    
    	//拆点,点上有容量限制
    	for (int i = 1; i <= n; ++i)
    	{
    		add(i, i + n, ma[i].q);
    	}
    
    	//源点到各点
    	for (int i = 1; i <= n; ++i)
    	{
    		bool flag = true;
    		for (int j = 1; j <= p; ++j)
    		{
    			if (ma[i].in[j] == 1)
    			{
    				flag = false;
    				break;
    			}
    		}
    		if (flag)
    		{
    			add(0, i, inf);
    		}
    	}
    
    	//各点到汇点
    	for (int i = 1; i <= n; ++i)
    	{
    		bool flag = true;
    		for (int j = 1; j <= p; ++j)
    		{
    			if (ma[i].out[j] != 1)
    			{
    				flag = false;
    				break;
    			}
    		}
    		if (flag)
    		{
    			add(i + n, t, inf);
    		}
    	}
    
    	for (int i = 1; i <= n; ++i)
    	{
    		for (int j = 1; j <= n; ++j)
    		{
    			bool flag = true;
    			for (int k = 1; k <= p; ++k)
    			{
    				if (!(ma[i].out[k] == ma[j].in[k] || ma[j].in[k] == 2))
    				{
    					flag = false;
    					break;
    				}
    			}
    			if (flag)
    			{
    				add(i + n, j, inf);
    			}
    		}			
    	}
    
    	while (bfs()) update();
    
    	printf("%d ", maxflow);
    
    	vector<re> v;
    	for (int i = 0; i <= idx; i += 2)
    	{
    		int b = e[i], a = e[i ^ 1], c = w[i];
    		if (b > n) continue;
    		if (a <= n) continue;
    		if (a == 0) continue;
    		if (inf - c)
    		{
    			v.push_back(re(a - n, b, inf - c));
    		}
    	}
    
    	printf("%d
    ", v.size());
    	for (int i = 0; i < v.size(); ++i)
    	{
    		printf("%d %d %d
    ", v[i].a, v[i].b, v[i].c);
    	}
    
    
    	return 0;
    }
    
  • 相关阅读:
    ISO、光圈、曝光、焦距
    错误: Could not edit the data in the folder or database selected. The current version does not support editing (base, consistent, or closed)
    SVN无法读取cruuent修复方法 Can't read file : End of file found 文件:txn_current、current
    visio 2010 修改 默认字体 字号大小 方法
    IE9最大化失效,最大化后顶端依然是桌面
    解决Excel导入Datatable 255字符限制(oledbdataadapter原理)
    关闭“子由门”FreeGate 无法 无线上网 有线网络可以上网
    进程死锁及解决办法
    纯css实现元素下出现横线动画(backgroundimage)
    html area标签详解
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/13298519.html
Copyright © 2011-2022 走看看