有n个关系,他们之间某些人相互认识。这样的人有m对。
你需要把人分成2组,使得每组人内部之间是相互不认识的。
如果可以,就可以安排他们住宿了。安排住宿时,住在一个房间的两个人应该相互认识。
最多的能有多少个房间住宿的两个相互认识。
先是要判断是否为二部图,然后求最大匹配。
学习一下模板~
#include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int maxn=1014; vector<int> g[maxn]; int linker[maxn]; bool used[maxn]; int uN; int matchs[maxn]; int cnt[maxn]; bool dfs (int u) { int i; for (i=0;i<g[u].size();i++) { int v=g[u][i]; if (!used[v]) { used[v]=true; if (linker[v]==-1||dfs(linker[v])) { linker[v]=u; return true; } } } return false; } int hungary () { int res=0; int u; memset(linker,-1,sizeof(linker)); for (u=1;u<=uN;u++) { memset(used,false,sizeof(used)); if (dfs(u)) res++; } return res; } bool judge (int x,int y) { int i; for (i=0;i<g[x].size();i++) { if (cnt[g[x][i]]==0) { cnt[g[x][i]]=-y; matchs[g[x][i]]=true; if (!judge(g[x][i],-y)) return false; } else if (cnt[g[x][i]]==y) return false; } return true; } bool matched () { int i; memset(matchs,false,sizeof(matchs)); for (i=1;i<=uN;i++) { if (g[i].size()&&!matchs[i]) { memset(cnt,0,sizeof(cnt)); cnt[i]=-1; matchs[i]=true; if (!judge(i,-1)) return false; } } return true; } int main () { int m; int i; int u,v; while (~scanf("%d %d",&uN,&m)) { for (i=1;i<=uN;i++) if (g[i].size()) g[i].clear(); while (m--) { scanf ("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } if (matched()) printf ("%d ",hungary()/2); else printf ("No "); } return 0; }