HDU 3081 Marriage Match II 网络流+二分
来源:互联网 发布:淘宝刷手会被处罚吗 编辑:程序博客网 时间:2024/06/01 08:28
题意:有n个女生和n个男生,一个女生可以和一个和她没有争吵的男生在一起,或者是和这个女生的女闺蜜没有争吵的男生在一起,给你m个点对,每个表示这个女生和这个男生没有争吵,再给你f个点对,表示这两个女生是闺蜜。每一轮游戏女生要选不同的男生,问你这样子的游戏,可以玩多少轮?
想法:可以想到这里要运用并查集处理女生的闺蜜关系,然后二分可以玩的回合数,由于每一回合女生都要找一个不同的男生,那么如果每一个女生都满足这个条件,那么不同的男生数量就是回合数了,网络流建边:设二分回合数是k
1.虚拟source和sink;
2.source到每一个女生连一条容量为k的边;
3.每一个女生向可以连接的男生连一条容量为1的边;
4.每一个男生向sink连一条容量为k的边;
如果最大流等于k*n表示游戏是可以进行到第k轮的。
使用dinic的时候记得加上反向弧优化
#include<iostream>#include<cstring>#include<cstdio>#include<queue>#define inf 0x7fffffffusing namespace std;const int nodes=500+5;const int edges=50000;int n,m,f,s,t;int father[nodes];struct node{ int v,next; int flow;}e[edges];struct nodee{ int a,b;}person[edges];int head[nodes],cur[nodes],cnt,ff[nodes];void Init(){ memset(head,-1,sizeof(head)); cnt=0;}class Dinic{ public: int spath() { queue<int>q; while(!q.empty()) q.pop(); memset(dis,-1,sizeof(dis)); dis[s]=0; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i+1;i=e[i].next) { int v=e[i].v; if(dis[v]==-1&&e[i].flow>0) { dis[v]=dis[u]+1; q.push(v); } } } return dis[t]!=-1; } int Min(int a,int b) { if(a<b) return a; return b; } int dfs(int u,int flow) { int cost=0; if(u==t) return flow; for(int &i=cur[u];i+1;i=e[i].next) { int v=e[i].v; if(dis[v]==dis[u]+1&&e[i].flow>0) { int min=dfs(v,Min(e[i].flow,flow-cost)); if(min>0) { e[i].flow-=min; e[i^1].flow+=min; cost+=min; if(cost==flow) break; } else dis[v]=-1; } } return cost; } int result() { int res=0; while(spath()) { for(int i=s;i<=t;i++) cur[i]=head[i]; res+=dfs(s,inf); } return res; } private: int dis[nodes];}dinic;class UF{ public: void Init() { for(int i=1;i<=200+5;i++) { father[i]=i; rank[i]=1; } } int find_set(int x) { if(x!=father[x]) father[x]=find_set(father[x]); return father[x]; } void union_set(int a,int b) { a=find_set(a); b=find_set(b); if(a==b) return; if(rank[a]>rank[b]) { rank[a]+=rank[b]; father[b]=a; } else { rank[b]+=rank[a]; father[a]=b; } } private: int rank[nodes];}uf;void add(int a,int b,int c){ e[cnt].v=b; e[cnt].flow=c; e[cnt].next=head[a]; head[a]=cnt++; e[cnt].v=a; e[cnt].flow=0; e[cnt].next=head[b]; head[b]=cnt++;}void Input(){ scanf("%d%d%d",&n,&m,&f); for(int i=0;i<m;i++) { scanf("%d%d",&person[i].a,&person[i].b); } for(int i=1;i<=f;i++) { int a,b; scanf("%d%d",&a,&b); uf.union_set(a,b); } for(int i=1;i<=n;i++) { ff[i]=uf.find_set(i); }}void build_map(int k){ s=0;t=2*n+1; Init(); for(int i=1;i<=n;i++) { add(s,i,k); add(i+n,t,k); } int vis[nodes][nodes]; memset(vis,0,sizeof(vis)); for(int i=0;i<m;i++) { int a=person[i].a; int b=person[i].b; for(int j=1;j<=n;j++) { if(ff[a]==ff[j]&&!vis[j][b]) { vis[j][b]=1; add(j,b+n,1); } } }}void treatment(){ int lft=0,rht=n; int max=0; while(lft<=rht) { int mid=(rht+lft)/2; build_map(mid); int k=dinic.result(); if(k==mid*n) { max=mid; lft=mid+1; } else { rht=mid-1; } } printf("%d\n",max);}int main(){ int t; scanf("%d",&t); while(t--) { uf.Init(); Input(); treatment(); } return 0;}
0 0
- HDU 3081 Marriage Match II 网络流+二分
- HDU 3081 Marriage Match II 二分+最大流
- HDU 3081 Marriage Match II(二分+最大流)
- HDU - 3081 Marriage Match II(二分+最大流)
- HDU 3081Marriage Match II(二分+并查集+网络流之最大流)
- HDU 3081 —— Marriage Match II(网络流,二分答案)
- HDU 3081 Marriage Match II 并查集加网络流
- hdu 3081 Marriage Match II isap+二分+并查集
- HDU 3081 Marriage Match II
- HDU 3081 Marriage Match II
- hdu 3081 Marriage Match II
- HDU-3081-Marriage Match II
- HDU 3081 Marriage Match II
- HDU 3081 Marriage Match II
- hdu 3081 Marriage Match II
- HDU-3081 Marriage Match II
- 【HDU】3081 Marriage Match II
- HDU 3081 Marriage Match II
- 转载 Hibernate的generator属性之意义
- 安卓新闻客户端(四)ViewPager使用
- Android——ButterKnife--View注入框架
- Minimum Path Sum
- Qt 绘制系统简介
- HDU 3081 Marriage Match II 网络流+二分
- C# 简单的日志文件制作
- Android最新优秀而实用的开源组件1
- Android Studio常用插件
- Canvas画简易的Calendar控件
- Android-Universal-Image-Loader三大组件DisplayImageOptions、ImageLoader、ImageLoaderConfiguration详解
- git初体验(四)git标签
- ToolBar的使用
- word 嵌入式图片不能显示,只显示一行。