POJ-1087 二分图匹配,最大流。
题意很迷,不过很水。
题意:一个房间有m个插座,每个插座有一个型号,现在有n台设备,每台设备指定了一种型号的插座,接下来有k个适配器,可以代替一种型号的插座。求最少有几台设备找不到插座。
因为每个插座只能允许一台设备接入,所以很容易想到匹配问题,对,开始用二分图匹配写的成功AC,然后改成了最大流,发现最大流建图更容易,一波板子AC。但两种写法都涉及到传递闭包,还有题目有个很多小坑点,注意一下就好了。
二分图:
const int N=800+10;
int n,m,k,g[N][N],linked[N],used[N];
void floyd(int num)//传递闭包
{
// printf("%d\n",num);
for(int k=1; k<=num; k++)
for(int i=1; i<=num; i++)
for(int j=1; j<=num; j++)
g[i][j]=g[i][j]||(g[i][k]&&g[k][j]);
// for(int i=1;i<num;i++)
// for(int j=1;j<num;j++)
// printf("i=%d j=%d %d\n",i,j,g[i][j]); }
bool dfs(int u)
{
for(int i=1; i<=m; i++)
if(!used[i]&&g[u][i])
{
used[i]=1;
if(linked[i]==-1||dfs(linked[i]))
{
linked[i]=u;
return true;
}
}
return false;
}
int hungary()
{
int res=0;
memset(linked,-1,sizeof(linked));
for(int i=m+n+101;i<=m+n+101+n;i++)
{
memset(used,0,sizeof(used));
if(dfs(i)) res++;
}
return n-res;
}
int main()
{
while(~scanf("%d",&m))
{
memset(g,0,sizeof(g));
map<string,int>q;
map<string,int>q1;
string plug,dev;
for(int i=1; i<=m; i++)
{
cin>>plug;
q[plug]=i;
}
scanf("%d",&n);
int tmpn=m+n+100,tmpm=m;
for(int i=1; i<=n; i++)
{
cin>>dev>>plug;
q1[dev]=++tmpn;
if(!q[plug]) q[plug]=++tmpm;
g[q1[dev]][q[plug]]=1;
}
scanf("%d",&k);
for(int i=1; i<=k; i++)
{
cin>>dev>>plug;
if(!q[dev]) q[dev]=++tmpm;
if(!q[plug]) q[plug]=++tmpm;
g[q[dev]][q[plug]]=1;//单向传递
// g[q[plug]][q[dev]]=1;
}
floyd(tmpn);
printf("%d\n",hungary());
}
return 0;
}
最大流:用0作为源点,与所有设备连边,容量为1,设备与对应型号插座连边,容量为1,别忘了传递闭包。插座和汇点连边,容量为1。注意,后出现的插座不能和汇点连边。
const int N=800+10;
int n,m,k;
int maze[N][N];
int gap[N],dis[N],pre[N],cur[N];
int flow[N][N];
void floyd(int num)//电器与插头之间传递闭包
{
for(int k=1; k<=num; k++)
for(int i=1; i<=num; i++)
for(int j=1; j<=num; j++)
maze[i][j]|=maze[i][k]&&maze[k][j];
}
int sap(int s,int t,int num)
{
memset(cur,0,sizeof(cur));
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
memset(flow,0,sizeof(flow));
int u=pre[s]=s,maxflow=0,aug=-1;
gap[0]=num;
while(dis[s]<num)
{
loop:
for(int v=cur[u]; v<num; v++)
if(maze[u][v]-flow[u][v]&&dis[u]==dis[v]+1)
{
if(aug==-1||aug>maze[u][v]-flow[u][v]) aug=maze[u][v]-flow[u][v];
pre[v]=u;
u=cur[u]=v;
if(v==t)
{
maxflow+=aug;
for(u=pre[u]; v!=s; v=u,u=pre[u])
{
flow[u][v]+=aug;
flow[v][u]-=aug;
}
aug=-1;
}
goto loop;
}
int mid=num-1;
for(int v=0; v<num; v++)
if(maze[u][v]-flow[u][v]&&mid>dis[v])
{
cur[u]=v;
mid=dis[v];
}
if((--gap[dis[u]])==0) break;
gap[dis[u]=mid+1]++;
u=pre[u];
}
return n-maxflow;
}
int main()
{
while(~scanf("%d",&m))
{
string dev,plug;
map<string,int>q;
map<string,int>q1;
memset(maze,0,sizeof(maze));
//1-n为电器,101开始都是插头
//原点为0,汇点为301--最坏情况;
int num=100,hui=301;
for(int i=1; i<=m; i++)
{
cin>>plug;
q[plug]=++num;
maze[q[plug]][hui]=1;//插头到汇点的容量为1;
}
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
cin>>dev>>plug;
q1[dev]=i;
maze[0][i]=1;//源点到电器,容量为1
if(!q[plug]) q[plug]=++num;
maze[i][q[plug]]=1;//电器到插头的容量为1;
}
scanf("%d",&k);
for(int i=1; i<=k; i++)
{
cin>>dev>>plug;
if(!q[dev]) q[dev]=++num;
if(!q[plug]) q[plug]=++num;
maze[q[dev]][q[plug]]=1;
}
floyd(300);
printf("%d\n",sap(0,301,302));
}
return 0;
}
POJ-1087 二分图匹配,最大流。的更多相关文章
- 最短路&生成树&二分图匹配&费用流问题
最短路 题意理解,建图 https://vjudge.net/problem/UVALive-4128 飞机票+行程建图 https://vjudge.net/problem/UVALive-3561 ...
- HDU3081:Marriage Match II (Floyd/并查集+二分图匹配/最大流(+二分))
Marriage Match II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- cogs_14_搭配飞行员_(二分图匹配+最大流,网络流24题#01)
描述 http://cojs.tk/cogs/problem/problem.php?pid=14 有一些正飞行员和副飞行员,给出每个正飞行员可以和哪些副飞行员一起飞.一架飞机上必须一正一副,求最多多 ...
- BZOJ 3546 Life of the Party (二分图匹配-最大流)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3546 题意:给定一个二分图.(AB两个集合的点为n,m),边有K个.问去掉哪些点后 ...
- POJ 3041 -- 二分图匹配
题意:有个N*N的网格,有一部分格子里有陨石,小明有很牛逼的武器,打一枪后一行或一列的陨石就没了,给出陨石分布,求最小打炮数. 分析:其实就是Konig定理.记最小打炮数为m,在网格里你最多可以找出M ...
- Antenna Placement POJ - 3020 二分图匹配 匈牙利 拆点建图 最小路径覆盖
题意:图没什么用 给出一个地图 地图上有 点 一次可以覆盖2个连续 的点( 左右 或者 上下表示连续)问最少几条边可以使得每个点都被覆盖 最小路径覆盖 最小路径覆盖=|G|-最大匹配数 ...
- POJ 1274 二分图匹配
匈牙利算法 裸题 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> ...
- luogu P3386 【模板】二分图匹配
二次联通门 : luogu P3386 [模板]二分图匹配 /* luogu P3386 [模板]二分图匹配 最大流 设置源点,汇点,连到每条边上 跑一边最大流即可 */ #include <i ...
- UVA 1663 Purifying Machine (二分图匹配,最大流)
题意: 给m个长度为n的模板串,模板串由0和1和*三种组成,且每串至多1个*,代表可0可1.模板串至多匹配2个串,即*号改成0和1,如果没有*号则只能匹配自己.问:模板串可以缩减为几个,同样可以匹配原 ...
- 【最大流,二分图匹配】【hdu2063】【过山车】
题意:裸的求二分图匹配 建立一个源点 连向一边所有的点 容量为1; 另外一边点都连向汇点 容量为1; 二分图的边容量也为1 源点汇点求一遍最大流即可 #include <cstdio> ...
随机推荐
- [转载]AngularJS快速开始
AngularJS快速开始 Hello World! 开始学习AngularJS的一个好方法是创建经典应用程序“Hello World!”: 使用您喜爱的文本编辑器,创建一个HTML文件,例如:hel ...
- a low memory warning should only destroy the layer’s bitmap
https://stablekernel.com/view-controller-in-ios-6/ Some of you may have noticed that your view contr ...
- NOIP2018初赛 解题报告
前言 \(NOIP2018\)初赛已经结束了,接下来就要准备复赛了. 不过,在此之前,还是先为初赛写一篇解题报告吧. 单项选择题 送分题.(虽然我还是做错了)可以考虑将它们全部转化为\(10\)进制, ...
- 浅谈KD-Tree
前言 \(KD-Tree\)是一个十分神奇的东西,其实本质上类似于一个\(K\)维的二叉搜索树. 核心思想 \(KD-Tree\)的核心思想与\(BST\)是差不多的(插入等操作也都基本上一样). 唯 ...
- 2018.6.20 Java考试试题总结(Java语言基础与面向对象编程)最新版
Java考试试题总结 一.单选题(每题1分 * 50 = 50分) 1.java程序的执行过程中用到一套JDK工具,其中javac.exe指( B ) A.java语言解释器 B.java字节码编译器 ...
- javascript同步和异步的区别与实现方式
javascript语言是单线程机制.所谓单线程就是按次序执行,执行完一个任务再执行下一个. 对于浏览器来说,也就是无法在渲染页面的同时执行代码. 单线程机制的优点在于实现起来较为简单,运行环境相对简 ...
- ASP.NET补充
字典类的子集 using System.Collections.Generic; Dictionary<string, string> dicB = new Dictionary<s ...
- Oracle 系统表
--如果一个表拥有DBA\\ALL\\USERS三个前缀 --DBA_前缀表示DBA拥有的或者可以访问的所有关系表 --ALL_前缀表示当前用户做拥有的或者可以访问的所有关系表 --USERS-前缀表 ...
- vue 自定义动态弹框
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 1046: [HAOI2007]上升序列
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5822 Solved: 2071[Submit][Status][Discuss] Descript ...