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
原创粉丝点击