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;
    }
    
  • 相关阅读:
    Linux下MySQL主从同步配置
    Tortoisegit图文使用教程
    C语言I博客作业06
    第十周助教总结
    C语言I博客作业04
    C语言I博客作业02
    第十一周助教总结
    第十二周助教总结
    第九周助教总结
    C语言I博客作业02
  • 原文地址:https://www.cnblogs.com/wzhh/p/11968055.html
Copyright © 2011-2022 走看看