题意:有n个学生,有m对人是认识的,每一对认识的人能分到一间房,问能否把n个学生分成两部分,每部分内的学生互不认识,而两部分之间的学生认识。如果可以分成两部分,就算出房间最多需要多少间,否则就输出No。
首先判断是否为二分图,然后判断最大匹配
Sample Input
4 4 1 2 1 3 1 4 2 3 6 5 1 2 1 3 1 4 2 5 3 6Sample Output
No 3
1 #include<iostream> 2 #include<string.h> 3 #include<vector> 4 #include<cstdio> 5 using namespace std; 6 #define MAXN 202 7 vector<int>EV[MAXN]; 8 int linker[MAXN]; 9 bool used[MAXN]; 10 int uN; 11 int matchs[MAXN],cnt[MAXN]; 12 bool dfs(int u) 13 { 14 int i; 15 for(i=0;i<EV[u].size();i++) 16 { 17 int v=EV[u][i]; 18 if(!used[v]) 19 { 20 used[v]=true; 21 if(linker[v]==-1||dfs(linker[v])) 22 { 23 linker[v]=u; 24 return true; 25 } 26 } 27 } 28 return false; 29 } 30 int hungary() 31 { 32 int res=0; 33 int u; 34 memset(linker,-1,sizeof(linker)); 35 for(u=1;u<=uN;u++) 36 { 37 memset(used,false,sizeof(used)); 38 if(dfs(u)) res++; 39 } 40 return res; 41 } 42 bool judge(int x,int y) //交叉染色法判断二分图 43 { 44 int i; 45 for(i=0;i<EV[x].size();i++) 46 { 47 if(cnt[EV[x][i]]==0) 48 { 49 cnt[EV[x][i]]=-1*y; 50 matchs[EV[x][i]]=true; 51 if(!judge(EV[x][i],-1*y)) return false; 52 } 53 else if(cnt[EV[x][i]]==y) return false; 54 } 55 return true; 56 } 57 bool matched() 58 { 59 int i; 60 memset(matchs,false,sizeof(matchs)); 61 for(i=1;i<=uN;i++) 62 { 63 if(EV[i].size()&&!matchs[i]) 64 { 65 memset(cnt,0,sizeof(cnt)); 66 cnt[i]=-1; 67 matchs[i]=true; 68 if(!judge(i,-1)) return false; 69 } 70 } 71 return true; 72 } 73 int main() 74 { 75 int m; 76 int i; 77 int u,v; 78 while(scanf("%d%d",&uN,&m)!=EOF) 79 { 80 for(i=1;i<=uN;i++) 81 if(EV[i].size()) EV[i].clear(); 82 while(m--) 83 { 84 scanf("%d%d",&u,&v); 85 EV[u].push_back(v); 86 EV[v].push_back(u); 87 } 88 89 if(matched()) 90 printf("%d\n",hungary()/2); 91 else printf("No\n"); 92 } 93 return 0; 94 }
时间: 2024-10-27 03:12:30