POJ-3436 ACM Computer Factory maximum flow, split point, output path, dinic

Topic link

POJ-3436

Title

There are n factories processing goods, the goods have m parts, and the factory has the largest capacity q. Tell you what kind of semi-finished products can be processed into each factory, and the condition of the products processed by this factory, and ask how many products can be produced at most.

Ideas

To be dismantled. . The ac was not removed for the first time, and the data did not get stuck.

First attach a set of hack data on POJ, which should output 10.

2 4
10 0 0 0 1
10 0 0 0 0
10 0 1 1 1
10 0 1 1 1

The problem of maximum flow, the key is to build a map, let’s talk about the building part first

  1. Split the points into two groups of in and out. 1-n represents in and n-2n represents out. The in-out of each factory is connected to the edge, and the capacity is the maximum capacity.
  2. Establish a super source sink, the source point is connected to the in edges of all factories that can be processed from scratch (specifically, the input data is that the m parts input by the factory are 0 or 2). The out of all processed factories (the m parts produced are all 1) are connected to the sink point. Capacity inf or maximum capacity
  3. Inter-factory connections, enumerate the out of each factory A, and connect to all the in-sides of factory B that can accept the products of the A factory (the output product of factory A is 0, and the product accepted by factory B can only be 0 or 2. A yields 1, B can only accept 1 or 2, A yields 2, no requirement for B). The capacity can be inf or maximum capacity.

The answer can be found by running the maximum flow algorithm. In addition, this question also requires outputting all factory connections, that is, the path used in the third step of the construction of the maximum flow. When we are building the map, we have established the reverse side. The initial capacity of the reverse side is 0. If the capacity of the reverse side is not 0, then this side must be used, and how much is used is the reverse side. capacity. Traverse all edges and output.

Code

#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<string>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib> 
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
using namespace std;
	typedef long long ll;
	const int inf=0x3f3f3f3f;
	const int maxn=200;
	const int maxe=100010;
	
	int ansu[maxe],ansv[maxe],answ[maxe];//最终输出 
	int nodev[maxn];//产能 
	int in_[maxn][15],out_[maxn][15];//输入输出产品标准 

	int head[maxn],cnt;
	struct Edge{
    
    
		int u;//改了下链式前向星,用于输出 
		int v;
		int w;
		int next;
	}edge[maxe];

	int n,m,s,t;
	ll maxflow;
	int deep[maxn];
	int now[maxe];

	void init(){
    
    
		memset(head,-1,sizeof(head));
		cnt=0;//我习惯从0开始建边,反向边就是1,3,5,7.。。。。 
		maxflow=0; 
		return ;	
	}
	void add(int u,int v,int w){
    
    
		edge[cnt].u=u;
  		edge[cnt].v=v;
		edge[cnt].w=w;
		edge[cnt].next=head[u];
		head[u]=cnt++;
	}

	inline bool bfs(){
    
    
    	memset(deep,0x3f,sizeof(deep));
    	queue<int>q;
    	q.push(s);deep[s] = 0;now[s] = head[s];
    	while(q.size()){
    
    
        	int x = q.front();q.pop();
        	for(int i=head[x];i!=-1;i=edge[i].next){
    
    
        	    int y=edge[i].v;
         	    if(edge[i].w>0&&deep[y]==inf){
    
    
         	    	q.push(y);
        	        now[y]=head[y];
         	       	deep[y]=deep[x]+1;
        	        if(y==t)	return 1;
				}
        	}
    	}
    	return 0;
	}
	ll dfs(int x,int flow){
    
    
    	if(x==t)	return flow;
    	ll ans = 0,k,i;
    	for(i=now[x];i!=-1&&flow;i=edge[i].next){
    
    
        	now[x]=i;
        	int y=edge[i].v;
        	if(edge[i].w>0&&(deep[y]==deep[x]+1)){
    
    
        	    k=dfs(y,min(flow,edge[i].w));
         		if(!k)	deep[y]=inf;
            	edge[i].w-=k;
            	edge[i^1].w+=k;
            	ans+=k;
            	flow-=k;
        	}
    	}
    	return ans;
	}	
	void dinic(){
    
    
    	while(bfs())
    	    maxflow+=dfs(s,inf);
	}
	
	int main(){
    
    	
		IOS
		cin>>m>>n;
		s=n+n+1,t=n+n+2;
    	init();
    	for(int i=1;i<=n;i++){
    
    
    		cin>>nodev[i];
    		for(int j=1;j<=m;j++)
    			cin>>in_[i][j];
    		for(int j=1;j<=m;j++)
    			cin>>out_[i][j];
		}
		//工厂间边 
		for(int i=1;i<=n;i++){
    
    
			for(int j=1;j<=n;j++){
    
    
				bool ok=1;
				for(int w=1;w<=m;w++){
    
    
					if((out_[i][w]==1&&in_[j][w]==0)||(out_[i][w]==0&&in_[j][w]==1)){
    
    
						ok=0;
						break;
					}
				}
				if(ok){
    
    
					add(i+n,j,min(nodev[i],nodev[j]));
					add(j,i+n,0);
				}
			}
		}
		//到这里为止,是答案需要我们输出的边,底下的不能输出 
		int cnt2=cnt;
		//源汇连边 
		for(int i=1;i<=n;i++){
    
    
			bool ok=1;
			for(int w=1;w<=m;w++)
				if(in_[i][w]==1){
    
    
					ok=0;
					break;
				}
			if(ok){
    
    
				add(s,i,nodev[i]);
				add(i,s,0);
			}
			ok=1;
			for(int w=1;w<=m;w++)
				if(out_[i][w]==0){
    
    
					ok=0;
					break;
				}
			if(ok){
    
    
				add(i+n,t,nodev[i]);
				add(t,i+n,0);
			}
		}
		//in-out边 
		for(int i=1;i<=n;i++){
    
    
			add(i,i+n,nodev[i]);
			add(i+n,i,0);
		}
    	dinic();
    	int mc=0;//边数量
		//1,3,5,7,9.。。是反向边 
    	for(int i=1;i<cnt2;i+=2){
    
    
    		if(edge[i].w){
    
    
				ansu[mc]=edge[i].v-n;
				ansv[mc]=edge[i].u;
				answ[mc]=edge[i].w;
    			mc++;
			}
		} 
    	cout<<maxflow<<" "<<mc<<endl;
    	for(int i=0;i<mc;i++)
    		cout<<ansu[i]<<" "<<ansv[i]<<" "<<answ[i]<<endl;
    	return 0;
	}

Guess you like

Origin blog.csdn.net/TheSunspot/article/details/108127317