Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5451 Accepted Submission(s): 2491
Input For each data set:
Output If these students cannot be divided into two groups, print "No". Otherwise, print the maximum number of pairs that can be arranged in those rooms.
Sample Input 4 4 1 2 1 3 1 4 2 3 6 5 1 2 1 3 1 4 2 5 3 6
Sample Output No 3
題目大意:有n個學生,有m對人是認識的,每一對認識的人能分到一間房,問能否把n個學生分成兩部分,每部分內的學生互不認識,而兩部分之間的學生認識。如果可以分成兩部分,就算出房間最多需要多少間,否則就輸出No。
思路:二分判定用染色法,找最大匹配數用匈牙利算法
代碼:
#include <iostream> #include <vector> #include <cstring> #include <cstdio> const int MAX=1e5+5; using namespace std; vector<int>mp[MAX]; int d[MAX],n,m,vis[MAX],link[MAX]; int dfs(int x,int f) //染色法 { d[x]=f; for(int i=0; i<mp[x].size(); i++) { if(d[x]==d[mp[x][i]]) return 0; int u=mp[x][i]; if(d[u]==0) if(!dfs(u,-f)) return 0; } return 1; } int dfs2(int x) //找最大匹配 { for(int i=0; i<mp[x].size(); i++) { int v=mp[x][i]; if(!vis[v]) { vis[v]=1; if(link[v]==-1||dfs2(link[v])) { link[v]=x; return 1; } } } return 0; } int find() //找最大匹配 { int res=0; memset(link,-1,sizeof(link)); for(int i=1; i<=n; i++) { memset(vis,0,sizeof(vis)); if(dfs2(i)) res++; } return res; } int main() { int a,b; while(cin>>n>>m) { for(int i=1; i<=n; i++) if(mp[i].size()) mp[i].clear(); for(int i=0; i<m; i++) { scanf("%d%d",&a,&b); mp[a].push_back(b); mp[b].push_back(a); } int flag=1; memset(d,0,sizeof(d)); for(int i=1; i<=n; i++) //染色 { if(mp[i].size()) if(!d[i]) if(!dfs(i,1)) { flag=0; break; } } if(!flag) cout<<"No"<<endl; else { cout<<find()/2<<endl; } } }