POJ3041 二分图最大匹配(网络流算法)

这题可以先构造一个二分图,它的|X|=|Y|=N,每当输入一个数对(x,y)时,连接一条x->y的边,求最小点覆盖即可。

最小点覆盖:对于一个二分图中的每一条边(u,v)都选其中一个顶点(多条边可以选同一点),使得选择的所有点的集合(无重复)元素的数量最小。——我想我已经解释地很清楚了……

最小点覆盖相当于最大匹配(证明见《算法艺术与信息学竞赛》,《算法导论》……),最大匹配我是用网络流(弱智办法)求的,附属代码:

#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
const int NMax=1500;
struct edge
{
    int num,len;
    edge *next,*rev;
}*S[NMax],pool[10000];
int N,K,nn,L;
void Build(int x,int y,int z)
{
    edge *p=&pool[L++],*q=&pool[L++];
    p->num=y; p->len=z; p->next=S[x];
    q->num=x; q->len=0; q->next=S[y];
    p->rev=q; q->rev=p;
    S[x]=p; S[y]=q;
}
int Q[NMax],level[NMax];
bool makelevel()
{
    int tmp;
    memset(level,-1,sizeof(level));
    Q[0]=0;
    level[0]=0;
    for(int i=0,bot=1;i<bot;i++)
    {
        tmp=Q[i];
        for(edge *p=S[tmp];p;p=p->next)
            if(p->len>0 && level[p->num]==-1)
                level[Q[bot++]=p->num]=level[tmp]+1;
    }
    return level[nn]!=-1;
}
int DFS(int a,int alpha)
{
    int tot=0,tmp;
    if(a==nn) return alpha;
    for(edge *p=S[a];p && tot<alpha;p=p->next)
        if(p->len>0 && level[p->num]==level[a]+1)
            if(tmp=DFS(p->num,min(alpha-tot,p->len)))
            {
                tot+=tmp;
                p->len-=tmp;
                if(p->rev!=NULL) p->rev->len+=tmp;
            }
    if(!tot) level[a]=-1;
    return tot;
}
int main()
{
    int x,y;
    scanf("%d%d",&N,&K);
    nn=N*2+1;
    for(int i=1;i<=K;i++)
    {
        scanf("%d%d",&x,&y);
        Build(x,N+y,1);
    }
    for(int i=1;i<=N;i++)
    {
        Build(0,i,1);
        Build(N+i,nn,1);
    }
    int ans=0,tmp;
    while(makelevel())
        while(tmp=DFS(0,(~0u>>1)))
            ans+=tmp;
    printf("%d\n",ans);
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值