zoukankan      html  css  js  c++  java
  • 上下界网络流学习笔记

    1、无源汇可行流

    对每条边(from,to,cap)改造

    cap=upper-lower

    inflow[to]+=lower

    outflow[from]+=lower

    然后对每个点Addedge(s,i,inflow[i]),Addedge(i,t,ouflow[i])

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    const int maxn=30000;
    const int oo=1000000000;
    
    int n,m;
    
    int inflow[maxn],outflow[maxn];
    
    struct Edge{
    	int from,to,cap,flow;
    };
    vector<int>G[maxn];
    vector<Edge>edges;
    void Addedge(int x,int y,int z){
    	Edge e;
    	e.from=x;e.to=y;e.cap=z;e.flow=0;
    	edges.push_back(e);
    	e.from=y;e.to=x;e.cap=0;e.flow=0;
    	edges.push_back(e);
    	int c=edges.size();
    	G[x].push_back(c-2);
    	G[y].push_back(c-1);
    }
    
    int s,t;
    queue<int>q;
    int vis[maxn];
    int d[maxn];
    int Bfs(){
    	memset(vis,0,sizeof(vis));
    	vis[s]=1;d[s]=0;q.push(s);
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		for(int i=0;i<G[x].size();++i){
    			Edge e=edges[G[x][i]];
    			if((e.cap>e.flow)&&(!vis[e.to])){
    				vis[e.to]=1;
    				d[e.to]=d[x]+1;
    				q.push(e.to);
    			}
    		}
    	}
    	return vis[t];
    }
    
    int Dfs(int x,int a){
    	if((x==t)||(a==0))return a;
    	
    	int nowflow=0,f=0;
    	for(int i=0;i<G[x].size();++i){
    		Edge e=edges[G[x][i]];
    		if((d[x]+1==d[e.to])&&((f=Dfs(e.to,min(a,e.cap-e.flow)))>0)){
    			nowflow+=f;
    			a-=f;
    			edges[G[x][i]].flow+=f;
    			edges[G[x][i]^1].flow-=f;
    			if(a==0)break;
    		}
    	}
    	return nowflow;
    }
    
    int Maxflow(){
    	int flow=0;
    	while(Bfs())flow+=Dfs(s,oo);
    	return flow;
    }
    
    int Lo[maxn];
    int main(){
    	scanf("%d%d",&n,&m);
    	
    	for(int i=1;i<=m;++i){
    		int x,y,l,h;
    		scanf("%d%d%d%d",&x,&y,&l,&h);
    		Addedge(x,y,h-l);
    		inflow[y]+=l;
    		outflow[x]+=l;
    		Lo[i*2-2]=l;
    	}
    	
    	s=n+1;t=s+1;
    	for(int i=1;i<=n;++i)Addedge(s,i,inflow[i]);
    	for(int i=1;i<=n;++i)Addedge(i,t,outflow[i]);
    	
    	Maxflow();
    	int fla=1;
    	for(int i=0;i<G[s].size();++i){
    		Edge e=edges[G[s][i]];
    		if(e.cap!=e.flow)fla=0;
    	}
    	
    	if(fla){
    		printf("YES
    ");
    		for(int i=0;i<m+m;i+=2){
    			printf("%d
    ",edges[i].flow+Lo[i]);
    		}
    	}else{
    		printf("NO
    ");
    	}
    	
    	return 0;
    }
    

      

     2、

    有源汇可行流

    Addedge(t,s,+oo)

    然后转化为无源汇可行流

    3、

    有源汇最大流

    先求出可行流

    然后跑s->t的最大流就为答案

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    const int maxn=100009;
    const int oo=1000000000;
    
    int ss,tt;
    int n,m;
    
    int inflow[maxn],outflow[maxn],suminflow=0;
    
    struct Edge{
    	int from,to,cap,flow;
    };
    vector<int>G[maxn];
    vector<Edge>edges;
    void Addedge(int x,int y,int z){
    	Edge e;
    	e.from=x;e.to=y;e.cap=z;e.flow=0;
    	edges.push_back(e);
    	e.from=y;e.to=x;e.cap=0;e.flow=0;
    	edges.push_back(e);
    	int c=edges.size();
    	G[x].push_back(c-2);
    	G[y].push_back(c-1);
    }
    
    int s,t;
    queue<int>q;
    int vis[maxn];
    int d[maxn];
    int Bfs(){
    	memset(vis,0,sizeof(vis));
    	vis[s]=1;d[s]=0;q.push(s);
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		for(int i=0;i<G[x].size();++i){
    			Edge e=edges[G[x][i]];
    			if((e.cap>e.flow)&&(!vis[e.to])){
    				vis[e.to]=1;
    				d[e.to]=d[x]+1;
    				q.push(e.to);
    			}
    		}
    	}
    	return vis[t];
    }
    
    int Dfs(int x,int a){
    	if((x==t)||(a==0))return a;
    	
    	int nowflow=0,f=0;
    	for(int i=0;i<G[x].size();++i){
    		Edge e=edges[G[x][i]];
    		if((d[x]+1==d[e.to])&&((f=Dfs(e.to,min(a,e.cap-e.flow)))>0)){
    			nowflow+=f;
    			a-=f;
    			edges[G[x][i]].flow+=f;
    			edges[G[x][i]^1].flow-=f;
    			if(a==0)break;
    		}
    	}
    	return nowflow;
    }
    
    int Maxflow(){
    	int flow=0;
    	while(Bfs())flow+=Dfs(s,oo);
    	return flow;
    }
    
    int main(){
    	scanf("%d%d%d%d",&n,&m,&ss,&tt);
    	s=n+1;t=s+1;
    	for(int i=1;i<=m;++i){
    		int x,y,lo,hi;
    		scanf("%d%d%d%d",&x,&y,&lo,&hi);
    		Addedge(x,y,hi-lo);
    		inflow[y]+=lo;
    		outflow[x]+=lo;
    		suminflow+=lo;
    	}
    	for(int i=1;i<=n;++i){
    		Addedge(s,i,inflow[i]);
    		Addedge(i,t,outflow[i]);
    	}
    	Addedge(tt,ss,oo);
    	
    	if(Maxflow()!=suminflow){
    		printf("please go home to sleep
    ");
    	}else{
    		s=ss;t=tt;
    		printf("%d
    ",Maxflow());
    	}
    	return 0;
    }
    

      4、有源汇上下界最小流

    先跑可行流

    然后把t->s的边删掉

    在跑t->s的最大流

    用t->s的边的流量- t->s的最大流

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    const int maxn=50009;
    const int oo=1000000000;
    
    int n,m,ss,tt;
    int inflow[maxn],outflow[maxn],suminflow;
    
    struct Edge{
    	int from,to,cap,flow;
    };
    vector<int>G[maxn];
    vector<Edge>edges;
    void Addedge(int x,int y,int z){
    	Edge e;
    	e.from=x;e.to=y;e.cap=z;e.flow=0;
    	edges.push_back(e);
    	e.from=y;e.to=x;e.cap=0;e.flow=0;
    	edges.push_back(e);
    	int c=edges.size();
    	G[x].push_back(c-2);
    	G[y].push_back(c-1);
    }
    
    int s,t;
    queue<int>q;
    int vis[maxn];
    int d[maxn];
    int Bfs(){
    	memset(vis,0,sizeof(vis));
    	vis[s]=1;d[s]=0;q.push(s);
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		for(int i=0;i<G[x].size();++i){
    			Edge e=edges[G[x][i]];
    			if((e.cap>e.flow)&&(!vis[e.to])){
    				vis[e.to]=1;
    				d[e.to]=d[x]+1;
    				q.push(e.to);
    			}
    		}
    	}
    	return vis[t];
    }
    
    int Dfs(int x,int a){
    	if((x==t)||(a==0))return a;
    	
    	int nowflow=0,f=0;
    	for(int i=0;i<G[x].size();++i){
    		Edge e=edges[G[x][i]];
    		if((d[x]+1==d[e.to])&&((f=Dfs(e.to,min(a,e.cap-e.flow)))>0)){
    			nowflow+=f;
    			a-=f;
    			edges[G[x][i]].flow+=f;
    			edges[G[x][i]^1].flow-=f;
    			if(a==0)break;
    		}
    	}
    	return nowflow;
    }
    
    int Maxflow(){
    	int flow=0;
    	while(Bfs())flow+=Dfs(s,oo);
    	return flow;
    }
    
    int main(){
    	scanf("%d%d%d%d",&n,&m,&ss,&tt);
    	for(int i=1;i<=m;++i){
    		int x,y,lo,hi;
    		scanf("%d%d%d%d",&x,&y,&lo,&hi);
    		inflow[y]+=lo;
    		outflow[x]+=lo;
    		Addedge(x,y,hi-lo);
    		suminflow+=lo;
    	}
    	s=n+1;t=s+1;
    	Addedge(tt,ss,oo);
    	for(int i=1;i<=n;++i){
    		Addedge(s,i,inflow[i]);
    		Addedge(i,t,outflow[i]);
    	}
    	
    	if(Maxflow()!=suminflow){
    		printf("please go home to sleep
    ");
    	}else{
    		int tm;
    		s=ss;t=tt;
    		for(int i=0;i<G[t].size();++i){
    			Edge e=edges[G[t][i]];
    			if(e.to==s&&e.cap==oo){
    				tm=edges[G[t][i]].flow;
    				edges[G[t][i]].flow=edges[G[t][i]].cap=0;
    				edges[G[t][i]^1].flow=edges[G[t][i]^1].cap=0;
    			}
    		}
    		swap(s,t);
    		printf("%d
    ",tm-Maxflow());
    	}
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    深入理解Java线程池
    BlockingQueue
    Synchronized的用法
    Java四种线程池的使用
    spring+mybatis之注解式事务管理初识(小实例)
    spring+mybatis之声明式事务管理初识(小实例)
    spring+mybatis结合实例
    MyBatis初识(通过小实例清晰认识MyBatis)
    Wordpress SEO
    Mysql 笔记二
  • 原文地址:https://www.cnblogs.com/zzyer/p/8564627.html
Copyright © 2011-2022 走看看