http://acm.hdu.edu.cn/showproblem.php?pid=2444
大意是给定n个学生,他们之间可能互相认识,首先判断能不能将这些学生分为两组,使组内学生不认识;
现想将学生两两分组,且保证每一组的学生都认识,这样分组可达到的最大组数为多大?
判断二分图,然后求匈牙利算法求最大匹配数
染色法判断二分图(脑抽用vector跑的特别慢)
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 using namespace std; 5 #define M 300 6 vector<int>line[M]; 7 int judge[M],p[M],q[M],used[M]; 8 int n; 9 int find() 10 { 11 memset(q,0,sizeof(q)); 12 int start=0,end=1; 13 q[start]=1; 14 memset(judge,-1,sizeof(judge)); 15 judge[1]=0; 16 while (start<end) 17 { 18 int w=q[start]; 19 for (int i=0;i<line[w].size();i++) 20 { 21 int e=line[w][i]; 22 if (judge[e]==-1){ 23 judge[e]=(judge[w]+1)%2; 24 q[end++]=e; 25 } 26 else{ 27 if (judge[e]==judge[w]) return 0; 28 } 29 } 30 start++; 31 } 32 return 1; 33 } 34 int sreach(int x) 35 { 36 int i,j; 37 for (j=1;j<=n;j++){ 38 for (i=0;i<line[j].size();i++) 39 { 40 if (line[j][i]==x&&!used[j]) 41 { 42 used[j]=1; 43 if (!p[j]||sreach(p[j])) 44 { 45 p[j]=x; 46 return 1; 47 } 48 } 49 } 50 } 51 return 0; 52 } 53 int main() 54 { 55 int t,i,m,a,b; 56 while (~scanf("%d %d",&n,&m)) 57 { 58 for (i=0;i<=n;i++) 59 line[i].clear(); 60 while (m--) 61 { 62 scanf("%d %d",&a,&b); 63 line[a].push_back(b); 64 line[b].push_back(a); 65 } 66 memset(p,0,sizeof(p)); 67 if (!find()){ 68 printf("No\n");continue; 69 } 70 int ans=0; 71 for (i=1;i<=n;i++) 72 { 73 memset(used,0,sizeof(used)); 74 if (sreach(i)) ans++; 75 } 76 printf("%d\n",ans/2); 77 } 78 return 0; 79 }
关系并查集判断二分图,类似于hdu 1829
#include<cstdio> #include<cstring> using namespace std; #define M 300 int father[M],line[M][M],used[M],p[M]; int n,rank[M]; void give() { for (int i=0;i<=200;i++){ father[i]=i;rank[i]=0; } } int find(int x) { if (x==father[x]) return father[x]; int t=find(father[x]); rank[x]=(rank[x]+rank[father[x]])%2; father[x]=t; return father[x]; } int sreach(int x,int n) { int i; for (i=1;i<=n;i++) { if (line[i][x]&&!used[i]) { used[i]=1; if (!p[i]||sreach(p[i],n)) { p[i]=x; return 1; } } } return 0; } int main() { int n,m,a,b,i; while (~scanf("%d %d",&n,&m)) { give(); int flag=0; memset(p,0,sizeof(p)); memset(line,0,sizeof(line)); while (m--) { scanf("%d %d",&a,&b); line[a][b]=line[b][a]=1; int sx=find(a); int sy=find(b); if (sx!=sy) { rank[sx]=(rank[a]+rank[b]+1)%2; father[sx]=sy; } else { if (rank[a]==rank[b]) flag=1; } } if (flag==1){ printf("No\n");continue; } int ans=0; for (i=1;i<=n;i++) { memset(used,0,sizeof(used)); if (sreach(i,n)) ans++; } printf("%d\n",ans/2); } return 0; }