poj 3084(最小割)
来源:互联网 发布:翻墙方式有哪些 知乎 编辑:程序博客网 时间:2024/05/12 08:37
大意就是,有一些房间,初始时某些房间之间有一些门,并且这些门是打开的,也就是可以来回走动的,但是这些门是确切属于某个房间的,也就是说如果要锁门,则只有在那个房间里才能锁,这跟现实很符合啊,不然随便个人站你家外边把你门给锁了是什么情况。 现在一些房间里有一些恐怖分子,要搞破坏,但是我们现在有个房间很重要,不能被他们破坏,这就需要锁一部分的门,不让恐怖分子有可趁之机,那么最少需要锁多个门呢?
很容易联系到最小割上面,刚开始我没读清楚,觉得既然门是可以来回走的,那么建个双向边好了,结果发现不是这样啊。
假设a->b代表a房间有个门到b,那么显然锁门的控制权在a上,锁1个门就可以不让b里面的人到a去,于是我们就建边b-a,容量为1,然后再建立边a->b,容量为无穷大,
为啥为无穷大呢,因为你无论怎么锁门,你在a里边可以随便开门,随便进入b,所以a->b这条边是锁不掉的
然后建立源点,与所有的存在恐怖分子的房间连边,容量为无穷大,因为题目也说了,可能有很多的锁很多的恐怖分子。
最后以被保护的那个房间为汇点,求最大流即可
#include<cstdio>#include<cstring>#include<map>#include<vector>#include<cmath>#include<cstdlib>#include<stack>#include<queue>#include <iomanip>#include<iostream>#include<algorithm>using namespace std ;const int N=100 ;const int M=20000 ;const int inf = 1<<30 ;struct node{int u,v,c,next;}edge[M] ;int head[N],pre[N],cur[N],dis[N],gap[N] ;int top ;void add(int u ,int v,int c) { edge[top].u=u; edge[top].v=v; edge[top].c=c; edge[top].next=head[u]; head[u]=top++; edge[top].u=v; edge[top].v=u; edge[top].c=0; edge[top].next=head[v]; head[v]=top++; } int sap(int s,int t ,int nv) { memset(dis,0,sizeof(dis)); memset(gap,0,sizeof(gap)); int u,v,minflow=inf,flow=0; for(int i = 0 ; i <nv ; i++) cur[i]=head[i] ; u=pre[s]=s; gap[s]=nv; while(dis[s] < nv ) { loop : for(int &j=cur[u] ; j!=-1 ; j=edge[j].next) { v=edge[j].v ; if(edge[j].c > 0 && dis[u] == dis[v] +1 ) { minflow = min(minflow ,edge[j].c) ; pre[v]=u; u=v ; if(v==t) { for( u =pre[v] ; v!=s ;v=u,u=pre[u]) { edge[cur[u]].c -= minflow ; edge[cur[u]^1].c += minflow ; } flow += minflow ; minflow = inf ; } goto loop ; } } int mindis=nv ; for(int i = head[u] ; i!=-1 ; i=edge[i].next) { v=edge[i].v ; if(edge[i].c > 0 && dis[v] < mindis) { mindis = dis[v] ; cur[u]=i ; } } if(--gap[dis[u]]==0) break ; gap[ dis[u] = mindis +1 ]++ ; u=pre[u] ; } return flow ; } int main(){int T ,t,q,x,n;char str[100] ;scanf("%d",&T);while(T--) { scanf("%d%d",&n,&t) ; t++; int s = 0 ; top = 0 ; memset(head,-1,sizeof(head)) ; for(int i = 1 ; i <= n ; i++) { scanf("%s%d",str,&q) ; while(q--) { scanf("%d",&x) ; add(i,x+1,inf) ; add(x+1,i,1) ; } if(str[0] == 'I') add(s,i,inf) ; }int ans = sap(s,t,n+1) ; if(ans >= inf ) puts("PANIC ROOM BREACH");else printf("%d\n",ans) ;} return 0;}
0 0
- poj 3084(最小割。。。。。)
- poj 3084 最小割
- poj 3084(最小割)
- poj 3084 最小割
- poj 3084(最小割)
- poj 3084(最小割)
- POJ 3084 Panic Room //最小割
- POJ 3084 Panic Room 最小割
- POJ 3084 Panic Room (最小割)
- POJ 3084 Panic Room | 最小割
- 【POJ】3084 Panic Room 最小割
- POJ 3084 Panic Room(最小割)
- POJ 3084 Panic Room 最小割
- POJ 3084 Panic Room(最小割)
- poj 3084 Panic Room 【最小割】
- POJ 3084 Panic Room 最小割
- poj--3084--Panic Room(最小割)
- poj 3469 最小割
- jQery事件绑定事件处理函数bind详解
- 什么都是新的
- linux之sed用法
- Android适配多分辨率注意事项
- xcode6 安装后无模拟器或更新完模拟器后无反应解决
- poj 3084(最小割)
- Java 二维数组根据维度升序或降序排序
- VirtualBox修改虚拟机磁盘VDI的大小
- 【v】2014/10/15:geoserver启动问题
- java 压缩与解压
- java中thread的start()和run()有何区别?
- 用户太多:互联网巨头之惑
- 一道Oracle SQL面试题及解答
- JD Git 使用