BZOJ 1433 浅谈二分图匹配及匈牙利算法
来源:互联网 发布:oracle filter 优化 编辑:程序博客网 时间:2024/06/02 03:27
世界真的很大
这道题在考试时做的时候是愣是觉得是一道水题,随随便便ac吧,这样,,,然后就wa了9个点,,,,原因实在太zz了就不分享了,但这道题是真的不难的,关乎于二分图匹配及基础的匈牙利算法。
description:
input:
output:
读完题大概就该往图论那边猜了,一个人只能睡一张床,人不能睡在别人身上,就是说一人一床匹配,床也不能坐在床身上,把床和人分开的话,就是一张二分图,在满足条件的情况下,跑一遍匈牙利算法,求出满足条件的最大匹配数,看是不是和住宿人数相等就行了。
首先是条件,即建边。人和床建双向边,一共有两种情况,即人是在校生还是来探访的,在校生如果回家就不管了,如果不回家,就可以睡自己的床,建一条边,来探访的对自己朋友的床建边,但不能对同为探访者建边,因为他没有床,代码:
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&x); if(whe[i]&&idf[i]) continue ; if(x&&idf[j]!=0) add(i,n+j),add(n+j,i); if(j==i&&idf[i]) add(i,n+j),add(n+j,i); }
接下来在建好的图上跑一遍匈牙利算法就行了,这里浅谈一下。
匈牙利算法是用于求二分图的最大匹配数的,虽然说dinic几乎能做匈牙利的所有题,但是毕竟好写,只有一个dfs。
举个例子:
这是一张二分图。
从一号点开始,找到一个没有被匹配的点A,将1与A互相记为一个匹配,退出,继续从e
2开始,重复以上步骤,2就找到了B:
接下来从3开始,找到了A,但是A已经被匹配了,就从A开始找增广路,我管这个叫协调,看1能不能找到一个新的匹配来把A空出来给3,1发现自己还可以和B匹配,就去和B协调,看B能不能让B的匹配,2,找到一个新的匹配从而把B空出来和1匹配,从而把A空出来和3匹配。发现2还可以和C匹配,就完美了,记录新的匹配。
加入4,从4开始找到C,C去找2看2能不能空出来,2去找B,发现B已经被协调过了,没法再协调了,不然又会让3落单,这时4就无法找到自己的匹配了,记录,这张二分图的最大匹配数就是3(绿色线)
dfs的代码如下:
int dfs(int u){ for(int i=head[u];i;i=ed[i].last) { int v=ed[i].v; if(book[v]==0) { book[v]=1; if(match[v]==0||dfs(match[v])) { match[u]=v; match[v]=u; return 1; } } } return 0;}
这道题的完整代码:
#include<stdio.h>#include<cstring>using namespace std;struct edge{ int v,last;}ed[100010];int head[100010],book[100010],match[100010],idf[100010],whe[100010];int num=0,n,tot=0,tt,x,cnt=0;void add(int u,int v){ num++; ed[num].v=v; ed[num].last=head[u]; head[u]=num;}int dfs(int u){ for(int i=head[u];i;i=ed[i].last) { int v=ed[i].v; if(book[v]==0) { book[v]=1; if(match[v]==0||dfs(match[v])) { match[u]=v; match[v]=u; return 1; } } } return 0;}int main(){ scanf("%d",&tt); while(tt--) { num=0,tot=0; memset(head,0,sizeof(head)); memset(idf,0,sizeof(idf)); memset(whe,0,sizeof(whe)); memset(match,0,sizeof(match)); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&idf[i]); for(int i=1;i<=n;i++) scanf("%d",&whe[i]); for(int i=1;i<=n;i++) if(idf[i]==1&&whe[i]==0) tot++; for(int i=1;i<=n;i++) if(idf[i]==0) tot++; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&x); if(whe[i]&&idf[i]) continue ; if(x&&idf[j]!=0) add(i,n+j),add(n+j,i); if(j==i&&idf[i]) add(i,n+j),add(n+j,i); } int ans=0; for(int i=1;i<=2*n;i++) { memset(book,0,sizeof(book)); if(!match[i]) if(dfs(i))ans++; } if(ans!=tot) printf("T_T\n"); else printf("^_^\n"); }}
嗯,就是这样。
- BZOJ 1433 浅谈二分图匹配及匈牙利算法
- bzoj 1191 匈牙利算法 二分图匹配
- 二分图匹配及匈牙利算法学习
- 二分图匹配及匈牙利算法
- BZOJ 1059 矩阵游戏(二分图匹配,匈牙利算法)
- bzoj 1059: [ZJOI2007]矩阵游戏|二分图匹配|匈牙利算法
- BZOJ 1433 假期的宿舍 (图论 二分图匹配 匈牙利算法)
- 二分图匹配:匈牙利算法
- 二分图匹配匈牙利算法
- 二分图匹配-匈牙利算法
- 匈牙利算法(二分图匹配)
- 二分图匹配 匈牙利算法
- 二分图匹配(匈牙利算法)
- 二分图匹配 匈牙利算法
- 二分图匹配-匈牙利算法
- 二分图匹配 匈牙利算法
- 二分图匹配匈牙利算法
- 二分图匹配-匈牙利算法
- hdoj1067 Gap(bfs+hash)
- 阿里巴巴最新面试经验-天猫进出口
- 气体传感器2
- mysql客户端调用load data infile报Error Code: 1045. Access denied for user错误
- tomcat原理解析(七):执行servlet
- BZOJ 1433 浅谈二分图匹配及匈牙利算法
- CABasicAnimation初始化通过animationwithkeypath的Key值设置动画
- Spring MVC中的@PathVariable
- golang 使用ffmpeg获取video的任意帧
- Java中的多线程
- 修改mysql端口号
- Android Studio使用svn出现E155036
- 基于网管软件的业务管控解决方案
- SAP中凭证类型的作用