网络流(二分图)


网络流(二分图)


匈牙利算法

主要的思想是利用点的让位关系,如果可以让位那就进行一位位的让出。实际上如果用网络流来进行分析,设S为源点,从S到左图每一个点连一条流量为1的边,从右图开始每一个点连一条流量为1的边到T点,中间为题目给出的路径。实际上分析匈牙利算法是在利用EK算法找残留网络的增广路径,所以时间复杂度为O(nm)。

bool Hungary(int p)
{
    //used每一次都要初始化,代表没有被使用。
	for(int j=1;j<=n;j++)	//遍历每一个点
		if(!used[j]&&f[p][j]==1)	//有路径同时没有被使用
		{
			used[j]=1;
			if(vis[j]==0||Hungary(vis[j])){
				vis[j]=p;
				return true;
			}
		}
	return false;
}

网络流解二分

#include<iostream>
#include<cstring>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
const int N=1e4+10,M=2e5+10;
int n,m,S,T,sum;
int head[N],idx,q[N],d[N],cur[N];
struct Edge{
    int next,to,f;
}edge[M];
void add(int a,int b,int c)
{
    edge[idx]=(Edge){head[a],b,c},head[a]=idx++;
    edge[idx]=(Edge){head[b],a,0},head[b]=idx++;
}
bool bfs()
{
    int hh=0,tt=0;
    memset(d,-1,sizeof d);
    q[0]=S,d[S]=0,cur[S]=head[S];
    while(hh<=tt)
    {
        int t=q[hh++];
        for(int i=head[t];~i;i=edge[i].next)
        {
            int ver=edge[i].to;
            if(d[ver]==-1&&edge[i].f)
            {
                d[ver]=d[t]+1;
                cur[ver]=head[ver];
                if(ver==T)  return true;
                q[++tt]=ver;
            }
        }
    }
    return false;
}
int find(int u,int limit)
{
    if(u==T)    return limit;
    int flow=0;
    for(int i=cur[u];~i&&flow<limit;i=edge[i].next)
    {
        cur[u]=i;   //当前弧优化
        int ver=edge[i].to;
        if(d[ver]==d[u]+1&&edge[i].f)
        {
            int t=find(ver,min(edge[i].f,limit-flow));
            if(!t)  d[ver]=-1;	//如果直接没有流量,就直接把这个点删除
            edge[i].f-=t;   edge[i^1].f+=t; flow+=t;
        }
    }
    return flow;
}
int dinic()
{
    int res=0,flow;
    while(bfs())   while(flow=find(S,inf))    res+=flow;
    return res;
}
int main()
{
    memset(head,-1,sizeof head);
    scanf("%d%d%d",&n,&m,&sum);	S=0,T=m+n+1;
    for(int i=1;i<=n;i++)	add(S,i,1);
    for(int i=1;i<=m;i++)	add(i+n,T,1);
    int a,b;
    while(sum--)
	{
		cin>>a>>b;
		add(a,b+n,1);
		}
    printf("%d\n",dinic());
    return 0;
}


文章作者: Dydong
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Dydong !
  目录