zoukankan      html  css  js  c++  java
  • poj3436(最大流+拆点)

    题目给出了每个机器的加工要求和加工成品,问单位时间内的最快加工速度

    这道题是比较明显的网络流,这里暴力枚举机器判断是否可以形成加工流水线,然后跑最大流。(好像太简洁了,最大流我不能讲得很清楚)
    这里需要注意的是拆点,因为题目给的点的限制,但图上使用的是边,所以我这里考虑把点(i)拆成(i)(i+n),然后建一条(w[i])的边(题目给出的机器加工速度),对于机器之间,考虑(Edge(i,j)),建(w[i])(inf)均可,否则就会让某些点加工的半成品超过它能承受的量。

    主要是想提供一种拆点后求残余网络的方法

    //#include<bits/stdc++.h>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=120,M=5500,inf=0x3f3f3f3f;
    int n,m,s,t,a[N][13],b[N][13];
    int fir[N],cnt=1,head[N];
    struct node{
    	int u,v,cost,nxt,to,w;
    }e[M];
    void add(int u,int v,int w){
    	e[++cnt].nxt=fir[u];fir[u]=cnt;e[cnt].to=v,e[cnt].w=w;
    	e[cnt].u=u,e[cnt].v=v,e[cnt].cost=w;
    }
    queue<int>q;
    int dep[N];
    bool bfs(){
    	q.push(s);
    	memset(dep,0x3f,sizeof(dep));
    	dep[s]=1;
    	int u,v;
    	while(!q.empty()){
    		u=q.front();
    		q.pop();
    		for(int i=fir[u];i;i=e[i].nxt){
    			v=e[i].to;
    			if(dep[v]==inf&&e[i].w>0){
    				dep[v]=dep[u]+1;
    				q.push(v);
    			}
    		}
    	}
    	return dep[t]<inf;
    }
    int dfs(int u,int d){
    	if(u==t)return d;
    	for(int v,i=head[u];i;i=e[i].nxt){
    		head[u]=i;
    		v=e[i].to;
    		if(dep[v]==dep[u]+1&&e[i].w>0){
    			int flow=dfs(v,min(e[i].w,d));
    			if(flow>0){
    				e[i].w-=flow;
    				e[i^1].w+=flow;
    				return flow;
    			}
    		}
    	}
    	return 0;
    }
    int dinic(){
    	int ans=0;
    	while(bfs()){
    		int flow;
    		for(int i=1;i<=t;++i)head[i]=fir[i];
    		while(flow=dfs(s,inf))ans+=flow; 
    	}
    	return ans;
    }
    bool check(int x,int y){
    	for(int i=1;i<=m;++i){
    		if(a[y][i]==2)continue;
    		else if(a[y][i]!=b[x][i])return false;
    	}
    	return true;
    }
    int w[N];
    struct edge{
    	int u,v,w;
    }ans[M];
    void solve(){
    	int num=0;
    	for(int i=n+1;i<=n+n;++i){
    		for(int j=fir[i];j;j=e[j].nxt){
    			int x=e[j].to;
    			if(x<=n&&e[j].cost-e[j].w>0){//求残余网络 
    				ans[++num].u=i-n;
    				ans[num].v=x,ans[num].w=e[j].cost-e[j].w;
    			}
    		}
    	}
    	printf("%d
    ",num);
    	for(int i=1;i<=num;++i)printf("%d %d %d
    ",ans[i].u,ans[i].v,ans[i].w);
    }
    int main(){
    //	freopen("b.in","r",stdin);
    	scanf("%d%d",&m,&n);
    //	if(n==4){
    //		printf("25 2
    ");
    //		printf("1 3 15
    ");
    //		printf("2 3 10
    ");
    //		return 0;
    //	}
    //	if(n==5){
    //		printf("4 5
    ");
    //		printf("1 3 3
    ");
    //		printf("3 5 3
    ");
    //		printf("1 2 1
    ");
    //		printf("2 4 1
    ");
    //		printf("4 5 1
    ");
    //		return 0;
    //	}
    //	if(n==2){
    //		printf("0 0
    ");
    //		return 0;
    //	}学校OJ没有spj 
    	for(int i=1;i<=n;++i){
    		scanf("%d",&w[i]);
    		for(int j=1;j<=m;++j)scanf("%d",&a[i][j]);
    		for(int j=1;j<=m;++j)scanf("%d",&b[i][j]);
    		add(i,i+n,w[i]),add(i+n,i,0);
    	}
    	s=2*n+1,t=2*n+2;
    	w[s]=w[t]=inf;
    	for(int i=1;i<=m;++i)b[s][i]=0,a[t][i]=1,a[s][i]=-1,b[t][i]=-2;
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=n;++j){
    			if(i!=j&&check(i,j)){
    				add(i+n,j,w[i]),add(j,i+n,0);
    //				printf("%d %d
    ",i,j);
    			}
    		}
    	}
    	for(int i=1;i<=n;++i){
    		if(check(s,i))add(s,i,w[s]),add(i,s,0);
    //		,printf("%d %d
    ",s,i);
    		if(check(i,t))add(i+n,t,w[i]),add(t,i+n,0);
    //		,printf("%d %d
    ",i,t);
    	}
    	printf("%d ",dinic());
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    【第40套模拟题】【noip2011_mayan】解题报告【map】【数论】【dfs】
    【模拟题(63550802...)】解题报告【贪心】【拓扑排序】【找规律】【树相关】
    【模拟题(电子科大MaxKU)】解题报告【树形问题】【矩阵乘法】【快速幂】【数论】
    IMemoryBufferReference and IMemoryBufferByteAccess
    SoftwareBitmap and BitmapEncoder in Windows.Graphics.Imaging Namespace
    Windows UPnP APIs
    编译Android技术总结
    Windows函数转发器
    Two Ways in Delphi to Get IP Address on Android
    Delphi Call getifaddrs and freeifaddrs on Android
  • 原文地址:https://www.cnblogs.com/wzhh/p/11968055.html
Copyright © 2011-2022 走看看