最大流 & 二分匹配模板

AC自动机: http://www.cppblog.com/mythit/archive/2009/04/21/80633.html

 

最大二分匹配模板    ZQUOJ  23124&&POJ  1469

 

#include<stdio.h>
 #include<string.h>
 int g[301][301],vis[301],match[301],count;    //g表示两点间是否有边,vis标记二分图右边的点是否访问过,match保存匹配的点
 int n,m;     //n右边的点的个数,m左边的点的个数
 int dfs(int v)
 {
     int i;
     for(i=1;i<=n;i++)      //遍历右边的顶点
     {
         if(!vis[i]&&g[v][i])     //没访问过且边<v,i>存在
         {
             vis[i]=1;
             if(dfs(match[i])||!match[i])
             {  //如果该点还未与其他点匹配,或还能找到其他点能与该点匹配的点match[i]进行匹配,即存在增广路
                 match[i]=v;     //将i与v进行匹配
                 return 1;
             }
         }
     }
     return 0;
 }
 void max_match()
 {
     int i;
     memset(match,0,sizeof(match));
     for(i=1;i<=m;i++)      //遍历左边的顶点
     {
         memset(vis,0,sizeof(vis));
         if(dfs(i))     //存在增广路径
             count++;
     }
 }
 int main()
 {
     int t,i,k,j,v;
     scanf("%d",&t);
     while(t--)
     {
         count=0;
         memset(g,0,sizeof(g));
         scanf("%d%d",&m,&n);
         for(i=1;i<=m;i++)
         {
             scanf("%d",&k);
             for(j=1;j<=k;j++)
             {
                 scanf("%d",&v);
                 g[i][v]=1;
             }
         }
         max_match();     //求最大二分匹配
         if(count==m)     //最大匹配数等于课程数
             printf("YES\n");
         else
             printf("NO\n");
     }
     return 0;
 }


最大流模板 hdu 3549  (ISAP)

 

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define N 505
#define inf 999999999
using namespace std;

int n,m,s,t,dis[N],pre[N],gap[N],flow[N][N];
struct edge
{
	int v,w;
	edge *next,*rev;
	edge(){next=0;}
	edge(int vv,int ww,edge *e){v=vv;w=ww;next=e;}
}*adj[N],*path[N],*e;
void insert(int u,int v,int w)
{
	edge *p=new edge(v,w,adj[u]);
	adj[u]=p;
	edge *q=new edge(u,0,adj[v]);
	adj[v]=q;
	p->rev=q;
	q->rev=p;
}
void bfs()
{
	memset(dis,0x7f,sizeof(dis));
	memset(gap,0,sizeof(gap));
	queue<int> q;
	dis[t]=0;
	gap[0]=1;
	q.push(t);
	while(q.size())
	{
		int x=q.front();
		q.pop();
		for(e=adj[x];e;e=e->next)
		{
			if(e->rev->w==0||dis[e->v]<t)
				continue;
			dis[e->v]=dis[x]+1;
			++gap[dis[e->v]];
			q.push(e->v);
		}
	}
}
int ISAP()
{
	memset(dis,0,sizeof(dis));
	memset(gap,0,sizeof(gap));
	//bfs();
	int ans=0,u=s,d;
	while(dis[s]<=t)
	{
		if(u==t)
		{
			int minflow=-1u>>1;
			for(e=path[u];u!=s;e=path[u=pre[u]])
				minflow=min(minflow,e->w);
			for(e=path[u=t];u!=s;e=path[u=pre[u]])
			{
				e->w-=minflow;
				e->rev->w+=minflow;
				flow[pre[u]][u]+=minflow;
				flow[u][pre[u]]-=minflow;
			}
			ans+=minflow;
		}
		for(e=adj[u];e;e=e->next)
			if(e->w>0&&dis[u]==dis[e->v]+1)
				break;
		if(e)
		{
			pre[e->v]=u;
			path[e->v]=e;
			u=e->v;
		}
		else
		{
			if(--gap[dis[u]]==0)
				break;
			for(d=t,e=adj[u];e;e=e->next)
				if(e->w>0)
					d=min(d,dis[e->v]);
			dis[u]=d+1;
			++gap[dis[u]];
			if(u!=s)
				u=pre[u];
		}
	}
	return ans;
}
int main()
{
	int u,v,w;
	int cas;
	scanf("%d", &cas);
	for(int k=1; k<=cas; k++)
	{
	    scanf("%d %d", &n, &m);
		memset(adj,0,sizeof(adj));
		while(m--)
		{
			scanf("%d%d%d",&u,&v,&w);
			insert(u,v,w);
			//insert(v,u,w);//无向边
		}
		s=1;
		t=n;
		printf("Case %d: %d\n", k, ISAP());
	}
}


 

 Dinic:

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 5005
#define M 10005
#define inf 999999999
using namespace std;

int n,m,s,t,num,adj[N],dis[N],q[N];
struct edge
{
	int v,w,pre;
}e[M];
void insert(int u,int v,int w)
{
	e[num]=(edge){v,w,adj[u]};
	adj[u]=num++;
	e[num]=(edge){u,0,adj[v]};
	adj[v]=num++;
}
int bfs()
{
	int i,x,v,tail=0,head=0;
	memset(dis,0,sizeof(dis));
	dis[s]=1;
	q[tail++]=s;
	while(head<tail)
	{
		x=q[head++];		
		for(i=adj[x];i!=-1;i=e[i].pre)
			if(e[i].w&&dis[v=e[i].v]==0)
			{
				dis[v]=dis[x]+1;
				if(v==t)
					return 1;
				q[tail++]=v;
			}
	}
	return 0;
}
int dfs(int s,int limit)
{
	if(s==t)
		return limit;
	int i,v,tmp,cost=0;
	for(i=adj[s];i!=-1;i=e[i].pre)
		if(e[i].w&&dis[s]==dis[v=e[i].v]-1)
		{
			tmp=dfs(v,min(limit-cost,e[i].w));
			if(tmp>0)
			{
				e[i].w-=tmp;
				e[i^1].w+=tmp;
				cost+=tmp;
				if(limit==cost)
					break;
			}
			else dis[v]=-1;
		}
	return cost;
}
int Dinic()
{
	int ans=0;
	while(bfs())
		ans+=dfs(s,INT_MAX);
	return ans;
}
int main ()
{
	while(~scanf("%d%d",&m,&n))
	{
		int u,v,w;
		memset(adj,-1,sizeof(adj));
		num=0;
		s=1;
		t=n;
		while(m--)
		{
			scanf("%d%d%d",&u,&v,&w);
			insert(u,v,w);
		}
		printf("%d\n",Dinic());
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值