hdu5285-wyh2000 and pupil-(染色法二分图判定)
http://acm.hdu.edu.cn/showproblem.php?pid=5285
题意:把互不认识的人分到两个组,第一组人数尽可能多。
题解:把互不认识的人连起来,当作二分图,二分图可能有多个,对于没有连线的点,扔到第一个图里。二色法对每个二分图染色,记录每个图比较多的颜色的数量累计到答案里。
特判坑:n<=1 或者 m==0
#include<stdio.h> #include<iostream> #include<algorithm> #include<cstring> #include<math.h> #include<string> #include<map> #include<queue> #include<stack> #include<set> #define ll long long #define inf 0x3f3f3f3f using namespace std; int n,m; vector<int>a[100005]; int color[100005]; int zero,one; int minn,maxx; bool flag; void bfs(int x) { queue<int>que;///对x点进行广搜,二色法,一个标记为0,另一个标记为1 zero=one=0; zero++; que.push(x); color[x]=0; while(!que.empty()&&flag) { int now=que.front(); que.pop(); int c=color[now]; int len=a[now].size(); for(int i=0;i<len;i++) { int next=a[now][i]; if(color[next]==-1)///如果没有被染色过, { que.push(next); if(c==0) color[next]=1,one++; else color[next]=0,zero++; } else ///被染色过 { if( color[next]==c ) { flag=false; break; } } } } } int main()//hdu5285 { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) a[i].clear(); memset(color,-1,sizeof(color)); minn=maxx=0; flag=true; if(n<=1) { printf("Poor wyh\n"); continue; } if(m==0)///特判,否则全部染成0色 { printf("%d 1\n",n-1); continue; } while(m--) { int u,v; scanf("%d%d",&u,&v); a[u].push_back(v); a[v].push_back(u); } int no=0;///没有被染色的点,其中第一组尽量多,则把没有染色的加到多的那一边去 for(int i=1;i<=n && flag;i++) { if(color[i]==-1 && a[i].size() )///没有被染色的点 并且 不是独立的 { bfs(i); if(zero<one) swap(zero,one); maxx+=zero; minn+=one; } else if(color[i]==-1 && a[i].size()==0)///独立的点染成颜色0,0是第一组,较多的那一组 { color[i]=0; maxx++; } } if(flag) printf("%d %d\n",maxx,minn); else printf("Poor wyh\n"); } return 0; }