POJ-3436 ACM Computer Factory flujo máximo, punto de división, ruta de salida, dinic

Enlace de tema

POJ-3436

Título

Hay n fábricas que procesan bienes, los bienes tienen m partes y la fábrica tiene la mayor capacidad q. Dígale qué tipo de productos semiacabados se pueden procesar en cada fábrica y el estado de los productos procesados ​​por esta fábrica, y pregunte cuántos productos se pueden producir como máximo.

Ideas

Para ser desmantelado. . El aire acondicionado no se demolió por primera vez y los datos no se atascaron.

Primero adjunte un conjunto de datos de pirateo en POJ, que debería generar 10.

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

El problema del flujo máximo, la clave es construir un mapa, hablemos primero de la parte del edificio

  1. Divida los puntos en dos grupos de entrada y salida. 1-n representa la entrada y n-2n representa la salida. El in-out de cada fábrica está conectado al borde y la capacidad es la capacidad máxima.
  2. Establezca un sumidero de súper fuente, el punto de fuente está conectado a los bordes internos de todas las fábricas que se pueden procesar desde cero (específicamente, los datos de entrada son que las m partes ingresadas por la fábrica son todas 0 o 2). De todas las fábricas procesadas (las m piezas producidas son todas 1) están conectadas al punto de hundimiento. Capacidad inf o capacidad máxima
  3. Conexiones entre fábricas, enumere las salidas de cada fábrica A y conéctelas a todas las partes internas de la fábrica B que pueden aceptar los productos de la fábrica A (el producto de salida de la fábrica A es 0, y el producto aceptado por la fábrica B solo puede ser 0 o 2. Lo que A produce es 1, lo que B solo puede aceptar es 1 o 2, y lo que A produce es 2, no hay ningún requisito para B). La capacidad puede ser inf o capacidad máxima.

La respuesta se puede encontrar ejecutando el algoritmo de flujo máximo. Además, esta pregunta también requiere que salgan todas las conexiones de fábrica, es decir, todas las rutas utilizadas en el tercer paso de la construcción del flujo máximo. Cuando estamos construyendo el mapa, hemos establecido el reverso, la capacidad inicial del reverso es 0. Si la capacidad del reverso no es 0, entonces se debe usar este lado y la cantidad que se usa es el reverso. capacidad. Atraviesa todos los bordes y la salida.

Código

#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;
	}

Supongo que te gusta

Origin blog.csdn.net/TheSunspot/article/details/108127317
Recomendado
Clasificación