zoukankan      html  css  js  c++  java
  • P2740 [USACO4.2]草地排水Drainage Ditches(dinic)

    Aimee

    显然这是一个网络流

    一开始,我们大可以随便找一条可行流

    然后再找一条,可是如果要返回怎么办?可以建立对应的反向边,反向边的容量即即为正向边流量,构成残余网络,在残余网络上找到的从s( ightarrow)t的路径,就是一条可行流,并且,找到最大流的充要条件是它的对应残余网络没有增广路

    这就是FF #方法

    那么怎么求呢,一下给出了dinic做法

    把残余网络用bfs序搞成分层图

    就是每一次在对应的残余网络上找不止一条增广路,对于每一个点,把尽可能多的流量分给子节点,之后后退,执行相同操作,最后更新残余网络,直到找不到增广路

    方案数?

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    int n,m,s,t;
    int p;
    int x,y,z;
    int head[205];
    long long Aimee;
    queue<int> q;
    struct e{
    	int to;
    	long long v;
    	int ne;
    } ed[200001];
    void add(int f,int t,int v){
    	ed[++p].ne=head[f];ed[p].to=t;ed[p].v=v;head[f]=p;
    	ed[++p].ne=head[t];ed[p].to=f;ed[p].v=0;head[t]=p;
    }
    int vis[200001];
    long long exf[200001];
    int pre[200001];
    int le[200001];
    int fr[200001];
    const long long inf= (1<<30);
    bool bfs(){
    	memset(le,-1,sizeof(le));
    	while(!q.empty()){
    		q.pop();
    	}
    	q.push(s);
    	le[s]=0;
    	fr[s]=head[s];
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int i=head[u];i;i=ed[i].ne){
    			int v=ed[i].to;
    			if(ed[i].v&&le[v]==-1){
    				q.push(v);le[v]=le[u]+1;
    				fr[v]=head[v];
    				if(v==t) return 1;
    			}
    		}
    	}
    	return 0;
    }
    long long dfs(int  now,int tas){
    	if(now==t) return tas;
    	long long znx=0;
    	for(int i=fr[now];i&&znx<tas;i=ed[i].ne){
    		fr[now]=i;
    		int v=ed[i].to;
    		if(ed[i].v&&le[v]==le[now]+1){
    			long long  jdn=dfs(v,min(tas-znx,ed[i].v));
    			if(!jdn) le[v]=-1;
    			ed[i].v-=jdn;
    			ed[i^1].v+=jdn;
    			znx+=jdn;
    		}
    	}
    	return znx;
    }
    long long znx;
    long long dinic(){
    	while(bfs()){
    		while(znx=dfs(s,inf)){
    			Aimee+=znx;
    		}
    	}
    	return Aimee;
    }
    int main(){
    	scanf("%d%d",&m,&n);
    	s=1;
    	t=n;
    	p=1;
    	for(int i=1;i<=m;++i){
    		scanf("%d%d%d",&x,&y,&z);
    		add(x,y,z);
    	}
    	cout<<dinic();
    	//printf("%lld",Aimee);
    	return 0;
    }
    
  • 相关阅读:
    Oracle数据库基础
    2016-08-08二期模拟考试
    易买网-登入
    常量接口模式
    反射
    Hhibernate延迟加载
    URL和URI的区别和联系
    Socket编程
    ArrayList如何实现线程安全
    移位运算符
  • 原文地址:https://www.cnblogs.com/For-Miku/p/14371698.html
Copyright © 2011-2022 走看看