【HDU】3081 Marriage Match II
2016-07-28 11:32
295 查看
Marriage Match II
题目链接
Marriage Match II题目大意
n个女生n个男生玩过家家~满足如下2个条件即可组成一对:女生a没和男生b吵过架
女生a的朋友c没和男生b吵过架
每个人都配对之后就继续玩下一轮,但是下一轮中每个人都必须选择一个另外的人配对,现在问最多玩多少轮。
题解
二分图 并查集
我们可以看到如果a的朋友b能和c配对,那么a也能和c配对,所以我们先用并查集处理出女生的朋友集合,然后对于每两个女生和男生的情况处理出所有的边。最后对整个图求最大匹配,当最大匹配与n相等的时候,先删去当前匹配边,再继续求最大匹配,当某个时刻最大匹配和n不相等,此时循环的次数就是答案。代码
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int T,n,m,f,b,a; int g[105][105],link[105],father[105]; bool vis[105]; int getfather(int k) { if (father[k]==k) return k; return father[k]=getfather(father[k]); } bool dfs(int u) { for (int i=1;i<=n;i++) if (!vis[i] && g[u][i]) { vis[i]=1; if (!link[i] || dfs(link[i])) { link[i]=u; return 1; } } return 0; } int solve() { int ans=0; memset(link,0,sizeof(link)); for (int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if (dfs(i)) ans++; } for (int i=1;i<=n;i++) if (link[i]) g[link[i]][i]=0; return ans; } int main() { scanf("%d",&T); while (T--) { for (int i=0;i<105;i++) father[i]=i; memset(g,0,sizeof(g)); scanf("%d%d%d",&n,&m,&f); for (int i=0;i<m;i++) { scanf("%d%d",&a,&b); g[a][b]=1; } for (int i=0;i<f;i++) { scanf("%d%d",&a,&b); int fa,fb; fa=getfather(a); fb=getfather(b); if (fa!=fb) father[fa]=fb; } for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { int f1,f2; f1=getfather(i); f2=getfather(j); if (f1==f2) for (int k=1;k<=n;k++) if (g[i][k]) g[j][k]=1; } int ans=0; while (solve()==n) ans++; printf("%d\n",ans); } return 0; }
相关文章推荐
- 仿ios右滑销毁activity
- 悖论的研究
- 《软件测试技术》课程
- 浏览器不支持JavaScript怎么办
- 基础总结篇之二:Activity的四种launchMode
- HDU1171
- linux 查看并发
- Java之反射及1.5新特性
- try catch
- js之json to string
- 如何禁止UITableView的section停留(去除卡住的效果)
- vijos 1146 - 采药
- webRTC源码VS编译指南
- 动态库与静态库优缺点比较
- Oracle中集合的使用
- javaweb学习总结(七)——HttpServletResponse对象(一)
- CSS中DIV只出现竖向滚动条且内容自动换行
- docker4dotnet #3 在macOS上使用Visual Studio Code和Docker开发asp.net core和mysql应用
- 一条SQL把两列的值通过函数得出另一个值时如何把它作为这条SQL的判断条件。
- Linux命令收录