最大流最小割

转载:https://blog.csdn.net/qq_41357771/article/details/79416899
https://blog.csdn.net/cai13160674275/article/details/50834431
EK

#include<iostream>
 #include<queue>
 using namespace std;
 const int maxn=205;
 const int inf=0x7fffffff;
 
int r[maxn][maxn]; //残留网络,初始化为原图
bool visit[maxn];
 int pre[maxn];
 int m,n;
 
bool bfs(int s,int t)  //寻找一条从s到t的增广路,若找到返回true
 {
     int p;
     queue<int > q;
     memset(pre,-1,sizeof(pre));
     memset(visit,false,sizeof(visit));
 
    pre[s]=s;
     visit[s]=true;
     q.push(s);
     while(!q.empty())
     {
         p=q.front();
         q.pop();
         for(int i=1;i<=n;i++)
         {
             if(r[p][i]>0&&!visit[i])
             {
                 pre[i]=p;
                 visit[i]=true;
                 if(i==t) return true;
                 q.push(i);
             }
         }
     }
     return false;
 }
 
int EdmondsKarp(int s,int t)
 {
    int flow=0,d,i;
    while(bfs(s,t))
    {
        d=inf;
        for(i=t;i!=s;i=pre[i])
            d=d<r[pre[i]][i]? d:r[pre[i]][i];
        for(i=t;i!=s;i=pre[i])
        {
            r[pre[i]][i]-=d;
            r[i][pre[i]]+=d;
        }
        flow+=d;
    }
    return flow;
 }
 
 
 int main()
 {
     while(scanf("%d%d",&m,&n)!=EOF)
     {
         int u,v,w;
         memset(r,0,sizeof(r));///
         for(int i=0;i<m;i++)
         {
             scanf("%d%d%d",&u,&v,&w);
             r[u][v]+=w;
         }
         printf("%d\n",EdmondsKarp(1,n));
     }
     return 0;
 }

EK

#include<iostream>
 #include<queue>
 using namespace std;
 const int maxn=205;
 const int inf=0x7fffffff;
 
int r[maxn][maxn]; //残留网络,初始化为原图
bool visit[maxn];
 int pre[maxn];
 int m,n;
 
bool bfs(int s,int t)  //寻找一条从s到t的增广路,若找到返回true
 {
     int p;
     queue<int > q;
     memset(pre,-1,sizeof(pre));
     memset(visit,false,sizeof(visit));
 
    pre[s]=s;
     visit[s]=true;
     q.push(s);
     while(!q.empty())
     {
         p=q.front();
         q.pop();
         for(int i=1;i<=n;i++)
         {
             if(r[p][i]>0&&!visit[i])
             {
                 pre[i]=p;
                 visit[i]=true;
                 if(i==t) return true;
                 q.push(i);
             }
         }
     }
     return false;
 }
 
int EdmondsKarp(int s,int t)
 {
    int flow=0,d,i;
    while(bfs(s,t))
    {
        d=inf;
        for(i=t;i!=s;i=pre[i])
            d=d<r[pre[i]][i]? d:r[pre[i]][i];
        for(i=t;i!=s;i=pre[i])
        {
            r[pre[i]][i]-=d;
            r[i][pre[i]]+=d;
        }
        flow+=d;
    }
    return flow;
 }
 
 
 int main()
 {
     while(scanf("%d%d",&m,&n)!=EOF)
     {
         int u,v,w;
         memset(r,0,sizeof(r));///
         for(int i=0;i<m;i++)
         {
             scanf("%d%d%d",&u,&v,&w);
             r[u][v]+=w;
         }
         printf("%d\n",EdmondsKarp(1,n));
     }
     return 0;
 }

Dinic

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 10005
#define MAXE 200005
using namespace std;
int n,m,S,T,hd,tl,que[MAXN],dep[MAXN];
int tot=-1,lnk[MAXN],nxt[MAXE],son[MAXE],C[MAXE],F[MAXE];
int read()
{
    int ret=0;
    char ch=getchar();
    bool f=1;
    for(; !isdigit(ch); ch=getchar())
        f^=!(ch^'-');
    for(; isdigit(ch); ch=getchar())
        ret=(ret<<3)+(ret<<1)+ch-48;
    return f?ret:-ret;
}
void add(int x,int y,int c,int f)
{
    son[++tot]=y;
    nxt[tot]=lnk[x];
    lnk[x]=tot;
    C[tot]=c;
    F[tot]=f;
}
bool BFS()
{
    hd=0;
    que[tl=1]=S;
    memset(dep,0,sizeof(dep));
    dep[S]=1;//更新点深度,可以说是刷层次
    while(hd!=tl)
    {
        int x=que[++hd];
        for(int j=lnk[x]; j!=-1; j=nxt[j])
            if(!dep[son[j]]&&C[j]>F[j])
                dep[son[j]]=dep[x]+1,que[++tl]=son[j];
    }
    return dep[T];
}
int DFS(int x,int flow)
{
    if(x==T)
        return flow;//到T点就停
    int now=0;
    for(int j=lnk[x]; j!=-1; j=nxt[j])
        if(dep[x]+1==dep[son[j]]&&C[j]>F[j])
        {
            int y=DFS(son[j],min(flow,C[j]-F[j]));//选出最小流量
            if(y>0)
            {
                F[j]+=y;    //进行更新
                F[j^1]-=y;
                now+=y;
                flow-=y;
                if(!flow)
                    return now;
            }
        }
    return now;
}
int Dinic()
{
    int ans=0;
    while(BFS())
        while(int t=DFS(S,1e9))
            ans+=t;
    return ans;
}
int main()
{
    memset(lnk,-1,sizeof(lnk));
    n=read(),m=read();
    S=read(),T=read();
    for(int i=1; i<=m; i++)
    {
        int x=read(),y=read(),z=read();
        add(x,y,z,0);
        add(y,x,z,z);
    }
    printf("%d\n",Dinic());
    return 0;
}

费用流
最大权闭合子图

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=105;
int n,m,T,s,t,Top,cur[MAXN],a[MAXN],Dep[MAXN],Ans,Sum;
struct Edge{
	int tot,lnk[MAXN],son[MAXN<<1],nxt[MAXN<<1];
	void clear(){memset(lnk,0,sizeof(lnk));tot=0;}
	void Add(int x,int y){nxt[++tot]=lnk[x];lnk[x]=tot;son[tot]=y;}
}S1,S2;
struct Flow{
	int tot,lnk[MAXN],son[MAXN<<3],nxt[MAXN<<3],C[MAXN<<3];
	void clear(){memset(lnk,-1,sizeof(lnk));tot=-1;}
	void Add(int x,int y,int c){nxt[++tot]=lnk[x];lnk[x]=tot;son[tot]=y;C[tot]=c;}
	void Add_E(int x,int y,int c){Add(x,y,c),Add(y,x,0);}
}E;
void DFS1(int x,int fa){
	if(fa) E.Add_E(x,fa,1<<30);
	for(int j=S1.lnk[x];j;j=S1.nxt[j]) if(S1.son[j]!=fa) DFS1(S1.son[j],x);
}
void DFS2(int x,int fa){
	if(fa) E.Add_E(x,fa,1<<30);
	for(int j=S2.lnk[x];j;j=S2.nxt[j]) if(S2.son[j]!=fa) DFS2(S2.son[j],x);
}
int hd,tl,que[MAXN];
bool BFS(){
	for(int i=s;i<=t;i++) Dep[i]=0;
	hd=0;que[tl=1]=s;Dep[s]=1;
	while(hd^tl){
		int x=que[++hd];
		for(int j=E.lnk[x];j^-1;j=E.nxt[j])
		if(!Dep[E.son[j]]&&E.C[j]) Dep[E.son[j]]=Dep[x]+1,que[++tl]=E.son[j];
	}
	return Dep[t];
}
int DFS(int x,int flow){
	if(x==t) return flow;
	for(int &j=cur[x],y;j^-1;j=E.nxt[j])
	if(Dep[x]+1==Dep[E.son[j]]&&E.C[j]>0&&(y=DFS(E.son[j],flow<E.C[j]?flow:E.C[j]))>0){E.C[j]-=y,E.C[j^1]+=y;return y;}
	return 0;
}
int Dinic(){
	int Sum=0;
	while(BFS()){
		for (int i=0;i<=t;i++) cur[i]=E.lnk[i];
		while(int Add=DFS(s,1<<30)) Sum+=Add;
	}
	return Sum;
}
int main(){
	freopen("theory.in","r",stdin);
	freopen("theory.out","w",stdout);
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);S1.clear(),S2.clear();Ans=0;Sum=0;
		for(int i=1;i<=n;i++) scanf("%d",&a[i]),Sum+=(a[i]>0?a[i]:0);
		for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),S1.Add(x,y),S1.Add(y,x);
		for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),S2.Add(x,y),S2.Add(y,x);
		s=0,t=n+1;
		for(int i=1;i<=n;i++){
			E.clear();DFS1(i,0);DFS2(i,0);
			for(int j=1;j<=n;j++) if(a[j]>0) E.Add_E(s,j,a[j]);else E.Add_E(j,t,-a[j]);
			Ans=max(Ans,Sum-Dinic());
		}
		printf("%d\n",Ans);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值