题意:
一些学生之间是朋友关系(关系不能传递)...现在要将一堆学生分成两堆,使得在同一堆的学生之间没有朋友关系..如果能成功..再问若把每对朋友关到小黑屋..最多能关多少对
题解:
这题就体现了二分图这个模型的基本条件...分为两个部分..内部没有边.边只在两个部分间...第一问..就是判断二分图..用染色的方法就好..下一问就是裸的匈牙利了...
Program:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<string.h>
#include<queue>
#define ll long long
#define esp 1e-5
#define MAXN 202
#define MAXM 50000000
#define oo 100000007
using namespace std;
int color[MAXN],match[MAXN];
bool used[MAXN];
vector<int> T[MAXN];
bool PutColor(int x,int tp)
{
if (color[x]==1-tp) return false;
if (color[x]==tp) return true;
color[x]=tp;
for (int i=0;i<T[x].size();i++)
if (!PutColor(T[x][i],!tp)) return false;
return true;
}
bool judge(int n)
{
memset(color,-1,sizeof(color));
for (int i=1;i<=n;i++)
if (color[i]==-1 && !PutColor(i,0)) return false;
return true;
}
bool dfs(int x)
{
for(int i=0;i<T[x].size();i++)
{
int y=T[x][i];
if (used[y]) continue;
used[y]=true;
if (!match[y] || dfs(match[y]))
{
match[y]=x;;
return true;
}
}
return false;
}
int getmax(int n)
{
int sum=0;
memset(match,0,sizeof(match));
for (int i=1;i<=n;i++)
if (color[i]==1)
{
memset(used,false,sizeof(used));
sum+=dfs(i);
}
return sum;
}
int main()
{
int i,n,m;
while (~scanf("%d%d",&n,&m))
{
for (i=1;i<=n;i++) T[i].clear();
while (m--)
{
int x,y;
scanf("%d%d",&x,&y);
T[x].push_back(y),T[y].push_back(x);
}
if (!judge(n)) { printf("No\n"); continue; }
printf("%d\n",getmax(n));
}
return 0;
}