Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5451 Accepted Submission(s): 2491
Input For each data set:
Output If these students cannot be divided into two groups, print "No". Otherwise, print the maximum number of pairs that can be arranged in those rooms.
Sample Input 4 4 1 2 1 3 1 4 2 3 6 5 1 2 1 3 1 4 2 5 3 6
Sample Output No 3
題目大意:有n個學生,有m對人是認識的,每一對認識的人能分到一間房,問能否把n個學生分成兩部分,每部分內的學生互不認識,而兩部分之間的學生認識。如果可以分成兩部分,就算出房間最多需要多少間,否則就輸出No。
思路:二分判定用染色法,找最大匹配數用匈牙利算法
代碼:
#include <iostream>
#include <vector>
#include <cstring>
#include <cstdio>
const int MAX=1e5+5;
using namespace std;
vector<int>mp[MAX];
int d[MAX],n,m,vis[MAX],link[MAX];
int dfs(int x,int f) //染色法
{
d[x]=f;
for(int i=0; i<mp[x].size(); i++)
{
if(d[x]==d[mp[x][i]])
return 0;
int u=mp[x][i];
if(d[u]==0)
if(!dfs(u,-f))
return 0;
}
return 1;
}
int dfs2(int x) //找最大匹配
{
for(int i=0; i<mp[x].size(); i++)
{
int v=mp[x][i];
if(!vis[v])
{
vis[v]=1;
if(link[v]==-1||dfs2(link[v]))
{
link[v]=x;
return 1;
}
}
}
return 0;
}
int find() //找最大匹配
{
int res=0;
memset(link,-1,sizeof(link));
for(int i=1; i<=n; i++)
{
memset(vis,0,sizeof(vis));
if(dfs2(i))
res++;
}
return res;
}
int main()
{
int a,b;
while(cin>>n>>m)
{
for(int i=1; i<=n; i++)
if(mp[i].size())
mp[i].clear();
for(int i=0; i<m; i++)
{
scanf("%d%d",&a,&b);
mp[a].push_back(b);
mp[b].push_back(a);
}
int flag=1;
memset(d,0,sizeof(d));
for(int i=1; i<=n; i++) //染色
{
if(mp[i].size())
if(!d[i])
if(!dfs(i,1))
{
flag=0;
break;
}
}
if(!flag)
cout<<"No"<<endl;
else
{
cout<<find()/2<<endl;
}
}
}