Accepts: 93
Submissions: 925
Time Limit: 3000/1500 MS (Java/Others)
Memory Limit: 131072/65536 K (Java/Others)
问题描述
青年理论计算机科学家wyh2000在教导他的小学生。 共有 n个小学生,编号为 1−n
。为了增加小学生之间的凝聚力,wyh2000决定将所有小学生分成 2
组,每组都至少有 1
个人。 但是有些小学生之间并不认识,而且如果 a
不认识 b
,那么 b
也不认识 a
。 Wyh2000希望每组中的小学生都互相认识。而且第一组的人要尽可能多。 请你帮wyh2000求出第一组和第二组的人数是多少。如果找不到分组方案,则输出"Poor wyh"。
输入描述
第一行一个数 T,表示数据组数。 对于每组数据,第一行两个数 n,m
,表示小学生数量和互相不认识的小学生的数量。 接下来 m
行,每行两个数 x,y(x<y)
,表示 x
不认识 y
, y
不认识 x
。保证一对 (x,y)
只会出现一次。 T≤10,0≤n,m≤100000
![]()
输出描述
对于每组数据,输出答案。
输入样例
2 8 5 3 4 5 6 1 2 5 8 3 5 5 4 2 3 4 5 3 4 2 4
输出样例
5 3 Poor wyh
题解:此题为二分图的写法,不过是多个二分图。只要求出全部二分图将每个二分图中人数最多的分在1组,就能得出答案。否则,二分图无法构建。
#include <iostream> #include <cstring> #include <cstdio> #include <string> #include <vector> using namespace std; vector<int> v[100005]; //保存不认识的人 int cnt[3]; //存储每一次查找到的二分图分别的人数 int color[100005]; //着色 bool dfs(int x) //从每一个节点出发深搜查找分成两部分 { for(int i = 0;i < v[x].size();i++) { int k = v[x][i]; if(-1 == color[k]) //如果没有着色,为此人着色,赋值为与上一个人相反, { color[k] = 3 - color[x]; //上一个为1,此人为2,否则为1; cnt[color[k]]++; if(!dfs(k)) //该人出发无法分成二分图 { return false; } } else if(color[k] == color[x]) //与二分图矛盾,即不认识的分在了一起 { return false; } } return true; //满足二分图条件 } int main() { int ncase; cin>>ncase; while(ncase--) { int ans = 0; int m,n; scanf("%d%d",&m,&n); int num1,num2; for(int i = 0;i <= m;i++) { v[i].clear(); } for(int i = 0;i < n;i++) { scanf("%d%d",&num1,&num2); v[num1].push_back(num2); v[num2].push_back(num1); } if(m < 2) //人数至少为2 { printf("Poor wyh\n"); continue; } memset(color,-1,sizeof(color)); bool flag = false; for(int i = 1;i <= m;i++) //从每一个人开始匹配二分图 { if(-1 == color[i]) //该人未分组,与此人有边的匹配成二分图,重复操作 { color[i] = 1; //着色1,2都一样 cnt[1] = 1; //1的人数 cnt[2] = 0; if(!dfs(i)) //无法匹配成二分图 { printf("Poor wyh\n"); flag = true; break; } ans += max(cnt[1],cnt[2]); //找到一个二分图,最多人数分在1组 } } if(flag) { continue; } if(ans == m) //每组至少一个人 { printf("%d %d\n",m - 1,1); } else { printf("%d %d\n",ans,m - ans); } } return 0; }