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. angular4路由设置笔记

    场景说明:angular4开发的一个后台项目 一.可以使用angular-cli创建一个带路由的项目,ng new 项目名称 --routing 会多创建一个app-routing.module.ts ...

  2. 【洛谷3950】部落冲突(LCT维护连通性)

    点此看题面 大致题意: 给你一棵树,\(3\)种操作:连一条边,删一条边,询问两点是否联通. \(LCT\)维护连通性 有一道类似的题目:[BZOJ2049][SDOI2008] Cave 洞穴勘测. ...

  3. Processing入门指南

    简介 Processing 是由 MIT 媒体实验室的 Casey Reas 和 Benjamin Fry 发明的一种开源可视化编程语言.Processing为数字媒体与娱乐交互设计而创建,其目的是通 ...

  4. 2018.7.1 css项目之模仿满屋花首页css+idv布局实现

    可以分开写 <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF ...

  5. DongDong坐飞机

    题目连接:https://ac.nowcoder.com/acm/contest/904/D 第一次研究了一下这种题型,还是比较好理解的,因为有半价次数的限制,所以要把每一中情况都写出来,dp[现在的 ...

  6. thymeleaf获取当前时间并格式化输出

    有时候会需要在模板中直接打印时间的需求,如果输出一个时间还需要在java类中去获取model的话,那未免也太麻烦了,以下为thymeleaf在模板中直接获取时间戳并格式化输的代码 获取时间戳 < ...

  7. PAT (Basic Level) Practise (中文)- 1005. 继续(3n+1)猜想 (25)

    http://www.patest.cn/contests/pat-b-practise/1005 卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况稍微有些复杂. 当我们验证 ...

  8. Andrew NG 自动化所演讲(20140707):DeepLearning Overview and Trends

    出处 以下内容转载于 网友 Fiona Duan,感谢作者分享 (原作的图片显示有问题,所以我从别处找了一些附上,小伙伴们可以看看).最近越来越觉得人工智能,深度学习是一个很好的发展方向,应该也是未来 ...

  9. Drupal忘记管理员密码

    第一步:登陆录到phpmyadmin(通用的mysql数据库管理工具),进入phpmyadmin后,找到与drupal7相关联数据库并在数据库中找到一张名为“users”的表,然后选择浏览. 第二步: ...

  10. numpy学习(二)

    ndarray的聚合操作 此博客讲的非常清楚,参照此博客即可 https://blog.csdn.net/qq_42571805/article/details/81146133