A Plug for UNIX

题意很迷,不过很水。

题意:一个房间有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 二分图匹配,最大流。的更多相关文章

  1. 最短路&生成树&二分图匹配&费用流问题

    最短路 题意理解,建图 https://vjudge.net/problem/UVALive-4128 飞机票+行程建图 https://vjudge.net/problem/UVALive-3561 ...

  2. HDU3081:Marriage Match II (Floyd/并查集+二分图匹配/最大流(+二分))

    Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  3. cogs_14_搭配飞行员_(二分图匹配+最大流,网络流24题#01)

    描述 http://cojs.tk/cogs/problem/problem.php?pid=14 有一些正飞行员和副飞行员,给出每个正飞行员可以和哪些副飞行员一起飞.一架飞机上必须一正一副,求最多多 ...

  4. BZOJ 3546 Life of the Party (二分图匹配-最大流)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3546 题意:给定一个二分图.(AB两个集合的点为n,m),边有K个.问去掉哪些点后 ...

  5. POJ 3041 -- 二分图匹配

    题意:有个N*N的网格,有一部分格子里有陨石,小明有很牛逼的武器,打一枪后一行或一列的陨石就没了,给出陨石分布,求最小打炮数. 分析:其实就是Konig定理.记最小打炮数为m,在网格里你最多可以找出M ...

  6. Antenna Placement POJ - 3020 二分图匹配 匈牙利 拆点建图 最小路径覆盖

    题意:图没什么用  给出一个地图 地图上有 点 一次可以覆盖2个连续 的点( 左右 或者 上下表示连续)问最少几条边可以使得每个点都被覆盖 最小路径覆盖       最小路径覆盖=|G|-最大匹配数 ...

  7. POJ 1274 二分图匹配

    匈牙利算法 裸题 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> ...

  8. luogu P3386 【模板】二分图匹配

    二次联通门 : luogu P3386 [模板]二分图匹配 /* luogu P3386 [模板]二分图匹配 最大流 设置源点,汇点,连到每条边上 跑一边最大流即可 */ #include <i ...

  9. UVA 1663 Purifying Machine (二分图匹配,最大流)

    题意: 给m个长度为n的模板串,模板串由0和1和*三种组成,且每串至多1个*,代表可0可1.模板串至多匹配2个串,即*号改成0和1,如果没有*号则只能匹配自己.问:模板串可以缩减为几个,同样可以匹配原 ...

  10. 【最大流,二分图匹配】【hdu2063】【过山车】

    题意:裸的求二分图匹配 建立一个源点 连向一边所有的点 容量为1; 另外一边点都连向汇点  容量为1; 二分图的边容量也为1 源点汇点求一遍最大流即可 #include <cstdio> ...

随机推荐

  1. double类型的小数,四舍五入保留两位小数

    import java.math.BigDecimal; public class Kewai{ public static void main(String[] args) { double f = ...

  2. DOM4j-中文API

    1.DOM4J简介       DOM4J是 dom4j.org 出品的一个开源 XML 解析包.DOM4J应用于 Java 平台,采用了 Java 集合框架并完全支持 DOM,SAX 和 JAXP. ...

  3. AngularJS1.X版本双向绑定九问

    前言 由于工作的原因,使用angular1.x版本已经有一段时间了,虽然angualr2升级后就完全重构了,但每个版本存在也有一定的道理.话不多说,进入正题. 1.双向绑定的原理是什么? Angual ...

  4. cf519C. A and B and Team Training(找规律)

    题意 $a$个学生,$b$个教练 可以两个学生和一个教练一组,也可以两个教练和一个学生一组,问最多组成多少组 Sol 发题解的目的是为了纪念一下自己的错误思路 刚开始想的是:贪心的选,让少的跟多的分在 ...

  5. 正则表达式通用匹配ip地址及主机检测

    在使用正则表达式匹配ip地址时如果不限定ip正确格式,一些场景下可能会产生不一样的结果,比如ip数值超范围,ip段超范围等,在使用正则表达式匹配ip地址时要注意几点: 1,字符界定:使用  \< ...

  6. 火狐IE event和target的兼容

    一.event对象 IE 中可以直接使用 window.event 对象,而 FF 中则不可以,解决方法之一如下: var theEvent = window.event || arguments.c ...

  7. tcl之基本语法—2

  8. tp5 修改自带success或error跳转模板页面

    tp5 修改自带success或error跳转模板页面 我们在使用tp5或者tp3.2的时候,用的成功或者失败跳转提示页面一般是用框架的.在后续开发过程中,根据实际项目需要,也是可以更改的,在此分享一 ...

  9. linux批量替换

    sed -i "s/李三/李四/g"  -r result/*       将result文件夹下的所有文件中的李三替换成李四 sed命令下批量替换文件内容  格式: sed -i ...

  10. PTA 数据结构——是否完全二叉搜索树

    7-2 是否完全二叉搜索树 (30 分) 将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),你需要判断最后的树是否一棵完全二叉树,并且给出其层序遍历的结果. 输入格 ...