判断一下是否为二分图。然后就是简单的二分图匹配了。。。
为什么是否为二分图,跟这道题有联系?
这道题如果同一边有认识的,那么输出‘NO’。可以把任意一个点标记为1,然后,跟他相连的的其余点标记为-1,然后,依次扩展。
这时候,如果一个点i跟他相连的其中一个点j已经标记了。那么,也就是说,i,j都已经跟起点各自归到了一边了。
如果,i,j的标记一样,那么,他们是在同一边的。不一样,那么,在不同边。
这个判断可以用来判断该图是否为二分图!
起点为X边,标记为1,标记为-1的为Y边,以起点开始依次扩展。如上述方法。
如果图中出现一个环,那么该环的节点数为偶数的话,则可以扩展为二分图,奇数的话,不可能为二分图。可以自己证明一下啦~。。~
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
int n,m;
int g[205][205];
int vis[205];
int link[205];
int c[205];
int flag;
void dfs(int v,int count)
{
for(int i=1;i<=n;i++)
if(g[v][i])
{
if(!c[i])
{
c[i]=-count;
dfs(i,c[i]);
}
else if(count==c[i])
flag=false;
if(flag==false)
return;
}
}
int judge()
{
memset(c,0,sizeof(c));
flag=true;
c[1]=1;
dfs(1,1);
return flag;
}
bool find(int v)
{
for(int i=1;i<=n;i++)
if(g[v][i] && !vis[i] )
{
vis[i]=1;
if( link[i]==-1 || find(link[i]) )
{
link[i]=v;
return true;
}
}
return false;
}
int main()
{
while(scanf("%d %d",&n,&m)==2)
{
memset(g,0,sizeof(g));
for(int i=0;i<m;i++)
{
int a,b;
scanf("%d %d",&a,&b);
g[a][b]=g[b][a]=1;
}
if(!judge())
{
printf("No\n");
continue;
}
int ans=0;
memset(link,-1,sizeof(link));
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(find(i))
ans++;
}
printf("%d\n",ans/2);
}
return 0;
}