传送门: The Accomodation of Students
解题思路:
1. 先把所有的人,分成互不认识的两组,如果不能分成,互不认识的两组,就输出No
2. 然后在就是二分图的匹配问题了。
实现代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 using namespace std; 6 7 const int MAXN=205; 8 9 vector<int>G[MAXN]; 10 11 int color[MAXN]; //讲顶点染成-1或1 12 int N; 13 14 bool dfs(int u,int c){ 15 color[u]=c; 16 for(int i=0;i<G[u].size();i++){ 17 if(color[G[u][i]]==c) return false; 18 if(color[G[u][i]]==0&&!dfs(G[u][i],-c)) 19 return false; 20 } 21 22 return true; 23 } 24 25 26 bool isBipartiesGraph(){ 27 memset(color,0,sizeof(color)); 28 for(int i=1;i<=N;i++) 29 if(color[i]==0){ 30 if(!dfs(i,1)) 31 return false; 32 } 33 return true; 34 } 35 36 int linker[MAXN]; 37 bool used[MAXN]; 38 bool findpath(int u){ 39 for(int i=0;i<G[u].size();i++){ 40 int v=G[u][i]; 41 if(!used[v]){ 42 used[v]=true; 43 44 if(linker[v]==-1||findpath(linker[v])){ 45 linker[v]=u; 46 return true; 47 } 48 } 49 } 50 return false; 51 } 52 53 int hungry(){ 54 int res=0; 55 memset(linker,-1,sizeof(linker)); 56 57 for(int u=1;u<=N;u++){ 58 memset(used,false,sizeof(used)); 59 if(findpath(u)) res++; 60 } 61 return res; 62 } 63 64 65 int main(){ 66 int M; 67 while(scanf("%d%d",&N,&M)!=EOF){ 68 for(int i=1;i<=N;i++) 69 G[i].clear(); 70 71 while(M--){ 72 int u,v; 73 scanf("%d%d",&u,&v); 74 G[u].push_back(v); 75 G[v].push_back(u); 76 } 77 78 if(N==1||!isBipartiesGraph()){ 79 printf("No "); 80 continue; 81 } 82 83 printf("%d ",hungry()/2); 84 } 85 }