HDU 3277 Marriage Match III 网络流(dinic 优化)+floyd
来源:互联网 发布:淘宝卖美女搞笑图片 编辑:程序博客网 时间:2024/05/17 02:38
题目大意:n个女生n个男生在一起玩耍,他们在玩一个“”结婚“的游戏,每局游戏女生找到一个男生作为自己的伴侣,每个女生可以找不和自己争吵的男生,如果一个女生和另外一个女生是好朋友,她也可以找和另外一个女生不争吵的男生作为自己的伴侣,另外有K次机会从所有的男生中选一个强制作为自己伴侣,每一局每个女生要找的男生都必须不相同,问这个游戏最多能进行多少局。
首先输入一个T代表T组样例,第二行输入四个整数,n,m,k,f,n代表有n个男生,n个女生,m代表男生女生的关系有m组,k代表女生有k次机会从所有男生中选一个作为伴侣,f代表女生和另一个女生认识的关系数量。
思路:首先一个女生要认识和另一个女生不争吵的男生我们可以用传递闭包来解决,floyd的第三层两个循环,一个是让女生之间互相认识,另一个是让女生认识男生。我们建立一个超级源点s=0,超级汇点t=3*n+1。超级源点连向每一个女生1~n,权值为我们二分寻找的答案mid,超级汇点连向每一个男生2*n~3*n,权值为我们二分要寻找的答案mid,然后我们把女生不争吵的男生之间连一条权值为1的边,代表这个女生可以直接找他。之后我们便要解决这个k了,k肯定是用在女生和可能争吵的男生之间的,我们把女生1~n和n+1~2*n之间连一条边权值为k的边,然后从n+1~2*n连向可能和女生争吵的男生之间,权值为1,这个拆点方法很巧妙,这样子跑一遍最大流,便是游戏最多的次数。
普通的dinic可能会超时,这里我用cur数组优化,代码如下:
#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#define inf 0x3fffffffusing namespace std;const int maxn=255;int first[maxn*3],sign,cur[255*3];int s,t,d[maxn*3];int mp[maxn*3][maxn*3];int n,m,k,f;struct node{ int to,w,next;}edge[maxn*maxn*maxn];void creat(){ memset(first,-1,sizeof(first)); sign=0;}void add_edge(int u,int v,int w){ edge[sign].to=v; edge[sign].w=w; edge[sign].next=first[u]; first[u]=sign++; edge[sign].to=u; edge[sign].w=0; edge[sign].next=first[v]; first[v]=sign++;}int bfs(){ queue<int>q; memset(d,0,sizeof(d)); d[s]=1; q.push(s); while(!q.empty()) { int top=q.front(); q.pop(); for(int i=first[top];~i;i=edge[i].next) { int to=edge[i].to; if(edge[i].w>0&&d[to]==0) { d[to]=d[top]+1; if(to==t) return 1; q.push(to); } } } return d[t]!=0;}int dfs(int top,int flow){ if(top==t) return flow; int ans=0,x=0; for(int i=cur[top];~i;i=edge[i].next) { int to=edge[i].to; if(edge[i].w>0&&d[to]==d[top]+1) { x=dfs(to,min(flow-ans,edge[i].w)); edge[i].w-=x; edge[i^1].w+=x; if(edge[i].w) cur[top] = i; ans+=x; if(ans==flow) return flow; } } if(ans==0) d[top]=0; return ans;}int dinic(){ int ans=0; while(bfs()) { for(int i=0;i<=3*n+1;i++) cur[i]=first[i]; ans+=dfs(s,inf); } return ans;}void floyd(){ for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) { if(mp[i][k]) { for(int j=1;j<=n;j++) { if(mp[i][k]&&mp[k][j]) { mp[i][j]=mp[j][i]=1; } } for(int j=2*n+1;j<=3*n;j++) { if(mp[i][k]&&mp[k][j]) { mp[i][j]=mp[j][i]=1; } } } } }}int judge(int mid){ creat(); for(int i=1;i<=n;i++) { add_edge(s,i,mid); } for(int i=2*n+1;i<=3*n;i++) { add_edge(i,t,mid); } for(int i=1;i<=n;i++) { add_edge(i,i+n,k); } for(int i=1;i<=n;i++) { for(int j=2*n+1;j<=3*n;j++) { if(mp[i][j]) { add_edge(i,j,1); } else { add_edge(i+n,j,1); } } } int tmp=dinic(); return tmp==mid*n;}int main(){ int T; scanf("%d",&T); { while(T--) { scanf("%d %d %d %d",&n,&m,&k,&f); int u,v,w; s=0,t=3*n+1; memset(mp,0,sizeof(mp)); for(int i=1;i<=m;i++) { scanf("%d %d",&u,&v); v+=2*n; mp[u][v]=mp[v][u]=1; } for(int i=1;i<=f;i++) { scanf("%d %d",&u,&v); mp[u][v]=mp[v][u]=1; } floyd(); int ans,l=0,r=n,mid; while(l<=r) { mid=(l+r)/2; if(judge(mid)) { ans=mid; l=mid+1; } else { r=mid-1; } } printf("%d\n",ans); } } return 0;}
阅读全文
0 0
- HDU 3277 Marriage Match III 网络流(dinic 优化)+floyd
- hdu 3277 Marriage Match III【并查集+最大流Dinic+拆点+建图+二分查找】
- 【hdu】3277 Marriage Match III【最大流】
- HDU 3277 Marriage Match III(二分+最大流)
- HDU 3277 Marriage Match III
- HDU 3277 Marriage Match III
- HDU 3277 Marriage Match III
- HDU 3277 Marriage Match III
- HDU 3277 Marriage Match III 二分+网络流拆点
- hdu 3416 Marriage Match IV 【图论-网络流-最短路+最大流(spfa + Dinic)】
- HDU 3277Marriage Match III(二分+并查集+拆点+网络流之最大流)
- Marriage Match III (hdu 3277 网络流+并查集+二分)
- HDU - 3277 Marriage Match III(并查集+最大流)
- 【网络流】hdu3277 Marriage Match III
- HDU -- 3277 Marriage Match III(最大流+二分+并查集+拆点)
- hdu 3277 Marriage Match III(最大流,二分,并查集)
- hdu 3416 Marriage Match IV【SPFA+最大流Dinic】
- HDOJ 3277 - Marriage Match III 拆点构图最大流..偷了一个效率很好的Dinic....
- AndroidObb文件编程中使用详解
- Python多线程和多进程编程
- Matlab中随机函数:rand函数,randn函数,randi函数
- Gym
- 3课:单片机存储器结构(温故知新)
- HDU 3277 Marriage Match III 网络流(dinic 优化)+floyd
- 如何通俗地解释 CGI、FastCGI、php-fpm 之间的关系?
- 图书查询时异常处理
- 提高系统性能之sql优化
- AngularJs+Spring MVC实现分页小结
- iOS模态跳转的页面WebView中加载html调用本机相册会dismiss返回上一个页面解决办法
- Windows系统下简易cms集成搭建(Apache+php+MySQL)
- Unit 8
- 学习git 和遇到的一个git问题的解决方案 2017-02 学习