HDU 2444 判断是否是二分图以及二分最大匹配

来源:互联网 发布:mac icon 尺寸 编辑:程序博客网 时间:2024/06/05 03:49

这个问题有几个要注意的地方。

第一个是黑白染色,留个模板好了,这里我用的是比较好看但效率比较低的dfs。

第二个问题是ans要不要除以2,这个问题我一开始和另一道题poj 1466混了些。



回到正题,这个问题的思路是,首先,用dfs黑白染色判断这个图是不是二分图,如果不是,输出no,如果是,就输出最大匹配数。

这里的ans是不用除以2的,而poj 1466这个问题是要除以2的。

因为poj那道是一定给你N个人的数据,谁谁相互认识一定会两次出现。比如,2认识4,在输入2这一组数据的时候会出现,而在输入4这一组数据的时候又会出现。而二分图那个“邻接矩阵”本身是单向的,所以这个关系就重复了,那么最后我们输出ans时候只需要把ans除以2就可以。

而这题只是给谁谁相互认识,默认了1认识2那么2就认识1。这样我们在建图的时候也就只有一遍记录这个关系,二分图储存的“邻接矩阵”是单向的嘛,所以不会重复匹配,ans也就不用除以2了。

上面解释给自己看……微笑

AC代码:

#include <iostream>#include <cstring>#include <string>#include <cstdio>#include <cstring>using namespace std;const int maxn=2e2+10;const int inf=0x3f3f3f3f;int K,N;bool mp[maxn][maxn];int mate[maxn];bool used[maxn];bool Findm(int x){    for(int i=1;i<=N;i++)    {        if(!used[i]&&mp[x][i])        {            used[i]=1;            if(!mate[i]||Findm(mate[i]))            {                mate[i]=x;                return 1;            }        }    }    return 0;}int color[maxn];//我并不是在mp这个图上染色而是用了color这个数组用序号表示点//用mp记录了关系,用color进行实际的染色、bool dfs_color(int s)//{    bool f=1;    for(int i=1;i<=N;i++)    {        if(mp[s][i])        {            if(color[i]==-1)            {                color[i]=!color[s];                f=dfs_color(i);                if(!f) return 0;            }            else if(color[s]==color[i])                return 0;        }    }    return 1;}int main(){    while(scanf("%d%d",&N,&K)!=EOF)    {        memset(mp,0,sizeof(mp));        for(int i=1;i<=K;i++)        {            int t1,t2;            scanf("%d%d",&t1,&t2);            mp[t1][t2]=1;        }        memset(color,-1,sizeof(color));//这样就不用记录是否染过色了。        color[1]=1;//别和上面那一句弄反了囧……        if(!dfs_color(1)) { printf("No\n"); continue; }        int ans=0;        memset(mate,0,sizeof(mate));        for(int i=1;i<=N;i++)        {            memset(used,0,sizeof(used));            ans+=Findm(i);        }        //printf("ans is %d\n",ans);        printf("%d\n",ans);    }}



阅读全文
0 0
原创粉丝点击