分析 && 题解:
需要判断是否为二分图并且如果是二分图,输出最大匹配。匈牙利算法加染色法判断即可PS:
需要注意的是,因为记录边的时候,同一条边被记录了两次,并且在匈牙利算法中,每次搜索的范围为所有点,所以每一对匹配都被算了两次,最后输出的时候应该除以2。AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
int n, m;
int Map[233][233];
int col[233];
int mark[233];
bool flag[233];
bool BFS(int s)
{
queue<int> q;
q.push(s);
col[s] = 1;
while(!q.empty())
{
int from = q.front();
q.pop();
for(int i=1; i<=n; i++)
{
if(Map[from][i] && col[i] == -1)
{
q.push(i);
col[i] = !col[from];
}
if(Map[from][i] && col[from]==col[i])
return false;
}
}
return true;
}
int b,g;
void Count()
{
for(int i=1;i<=n;i++)
{
if(col[i]) b++;
else g++;
}
}
bool DFS(int x)
{
for(int i=1;i<=n;i++)
{
if(!Map[x][i]||flag[i])
continue;
flag[i] = 1;
if(!mark[i]||DFS(mark[i]))
{
mark[i] = x;
return 1;
}
}
return 0;
}
void Hungarian()
{
int ans = 0;
memset(mark, 0, sizeof(mark));
for(int i=1;i<=n;i++)
{
memset(flag, 0, sizeof(flag));
if(DFS(i))
{
ans++;
}
}
cout << ans/2 << endl;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(Map, 0, sizeof(Map));
for(int i=1;i<=m;i++)
{
int x,y;
cin >> x>>y;
Map[x][y] = 1;
Map[y][x] = 1;
}
memset(col, -1, sizeof(col));
bool flag = false;
for(int i=1;i<=n;i++)
{
if(col[i] == -1 && !BFS(i ))
{
flag = true;
break;
}
}
if(flag)
{
cout << "No" << endl;
}
else
{
b=0;g=0;
Count();
Hungarian();
}
}
return 0;
}