原题链接:点击打开链接
题意:给出一些学生,他们可能是朋友,要确定这些学生是否能分成两组,每组之间的同学彼此没有关系,若能分成两组,再求有多少组两人一组的学生,每个学生隶属一组,
思路:染色判断是否为二分图,若为二分图,再求最大匹配数;
PS:bfs判断是否为二分图;将相邻的点染上不同的颜色,若在染色过程中发现相邻的点为同色,则说明不是二分,仔细看代码
code:
#include <iostream>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <queue>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
vector<int >vec[210];
int vis[210],link[210];
int n, m;
int cnt;
int bfs()//判断是否为二分图
{
memset(vis,-1,sizeof(vis));
for(int i=1;i<=n;i++)
{
if(vis[i]!=-1)
continue;
vis[i]=1;
queue<int >q;
q.push(i);
while(!q.empty())
{
int k=q.front();
q.pop();
for(int j=0;j<vec[k].size();j++)
{
int tem=vec[k][j];
if(vis[tem]==vis[k])
return 0;
if(vis[tem]==-1)
{
q.push(tem);
vis[tem]=1-vis[k];//1 || 0;
}
}
}
}
return 1;
}
int dfs(int s)
{
for(int i=0;i<vec[s].size();i++)
{
int tem=vec[s][i];
if(!vis[tem])
{
vis[tem]=1;
if(link[tem]==-1 || dfs(link[tem]))
{
link[tem]=s;
return 1;
}
}
}
return 0;
}
int hungary()
{
memset(link,-1,sizeof(link));
int ans=0;
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(dfs(i))
ans++;
}
return ans;
}
int main()
{
//freopen("i.txt","r",stdin);
int i,j,a,b;
while(~scanf("%d%d", &n, &m))
{
for(i=0;i<=n;i++)
vec[i].clear();
while(m--)
{
scanf("%d%d",&a,&b);
vec[a].push_back(b);
vec[b].push_back(a);
}
if(!bfs())
{
printf("No\n");
continue;
}
printf("%d\n",hungary()/2);
}
return 0;
}