对每两个不认识的人连一条边,则此题可转化为二分图判定(用染色法。注意:二分图可有多个)。
如果有一部分图判定为不是二分图,则输出“Poor wyh”。
否则,分别累加每个二分图的最多的颜色数。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
typedef long long ll;
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=100000+10;
vector <int> g[maxn];
int color[maxn];//-1代表无颜色,0和1代表两种对立的颜色。
int n,m;
int bfs(int s){
//printf("bfs: %d\n",s );
queue<int>q;
q.push(s);
color[s]=0;
int n1=0,n0=0;//统计两种颜色的个数。
while(!q.empty()){
int start=q.front();
q.pop();
if(color[start]==0)n0++;
else n1++;
int len=g[start].size();
for(int i=0;i<len;++i){
int tmp=g[start][i];
//printf("this is %d-%d\n",start,tmp );
if( color[ tmp ]==-1 ){
q.push(tmp);
color[tmp]=( color[start]+1 )%2;
}
else if(color[start]==color[tmp]){
//printf("color[%d]==color[%d]\n",start,tmp);
return -1;
}
}
}
return max(n0,n1);
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)g[i].clear();
memset(color,-1,sizeof color);
int u,v;
for(int i=0;i<m;++i){
scanf("%d %d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
int ans=0;
for(int i=1;i<=n;++i){
if(color[i]==-1){
int rtn=bfs(i);
//printf("rtn==%d\n",rtn );
if(rtn==-1){//此处少写个等号,害我Debug半天。改正后,一次AC
ans=-1;
break;
}
ans+=rtn;
}
}
//printf("ans==%d\n", ans);
if(ans==-1 || n<2 ){
printf("Poor wyh\n");
}else if(ans==n){
printf("%d %d\n",ans-1,n-ans+1 );
}else {
printf("%d %d\n",ans,n-ans );
}
}
return 0;
}
PS:这道题是我第一次用Vector表示图 :)