• 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;
    }
    
  • 相关阅读:
    【leetcode】1365. How Many Numbers Are Smaller Than the Current Number
    【leetcode】1363. Largest Multiple of Three
    【leetcode】1362. Closest Divisors
    【leetcode】1361. Validate Binary Tree Nodes
    【leetcode】1360. Number of Days Between Two Dates
    【leetcode】1359. Count All Valid Pickup and Delivery Options
    【leetcode】1357. Apply Discount Every n Orders
    【leetcode】1356. Sort Integers by The Number of 1 Bits
    ISE应用入门的一些问题
    DDR的型号问题
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/13298519.html
Copyright © 2020-2023  润新知