poj 3084 最小割

  1 /*
  2 题意:给出m个房间,给出房间的连接情况,样例中给出的是第i间房可以到达t号房,而且
  3 是无法阻止的,因为控制器在第i间房的这边,而且两个房间可以有多扇门;问最少要关闭
  4 多少个门锁才使得入侵者无法到达n号房间(如果在控制器的这一边,则即使锁上也无法防止
  5 入侵者走这扇门);
  6 
  7 题解:最小割==最大流
  8 关键是建图,题目给出的是i->j是连通的,然后我们要加的是逆向边j->i,权值为1,表示要
  9 阻止入侵者需要通过这些们进入房间j需要锁上1把锁,里面的重边就表示有多扇门都需要上
 10 锁;然后再加边i->j,权值为inf,表示要加上无限把锁才能阻止入侵者(即不可能,因为有控
 11 制器),然后加入源点0,与所有入侵者点相连,权值为inf,表示源点出发到这些点必然能够
 12 进入(这是显然的),然后就是求0到n的最小割,最少的权值和能将n点与入侵者的点分开,
 13 返回的最大流的值如果大于等于inf则表示找不到这样的最小割,输出失败信息;
 14 这里从源点0到入侵者点的边初始为inf,因此找到的最大流小于inf则必然是全部从原图中的
 15 边找到而不包含源点连接的边
 16 */
 17 #include <cstdio>
 18 #include <cstring>
 19 #define clr(a,b) (memset(a,b,sizeof(a)))
 20 #define cpy(a,b) (memcpy(a,b,sizeof(b)))
 21 const int I = 0x7f7f7f7f;
 22 const int NV = 500;
 23 const int NE = 100000;
 24 int n,m;
 25 int start,end;
 26 inline int Min(int a,int b) {return a < b ? a : b;}
 27 struct MF {
 28        int pre[NV],gap[NV],dis[NV],head[NV],cur[NV];
 29        int node,nodenum;
 30        struct edge {
 31               int s,t,val,next;
 32               edge(){}
 33               edge(int _s,int _t,int _val,int _next) :
 34                      s(_s),t(_t),val(_val),next(_next){}
 35        }E[NE];
 36        inline void init(int num) {
 37               nodenum = num;
 38               clr(head,-1);
 39               node = 0;
 40        }
 41        inline int sap(int s,int t) {
 42               int i;
 43               clr(dis,0);
 44               clr(gap,0);
 45               cpy(cur,head);
 46               int u = pre[s] = s,v,maxflow = 0;
 47               int mi = I;
 48               gap[0] = nodenum;
 49               while(dis[s] < nodenum) {
 50 loop:
 51                      for(int &e = cur[u];e != -1;e = E[e].next) {
 52                             v = E[e].t;
 53                             if(E[e].val && dis[u] == dis[v] + 1) {
 54                                    mi = Min(mi,E[e].val);
 55                                    pre[v] = u;
 56                                    u = v;
 57                                    if(v == t) {
 58                                           maxflow += mi;
 59                                           for(u = pre[u];v != s;v = u,u = pre[u]) {
 60                                                  E[ cur[u] ].val -= mi;
 61                                                  E[ cur[u]^1 ].val += mi;
 62                                           }
 63                                           mi = I;
 64                                    }
 65                                    goto loop;
 66                             }
 67                      }
 68                      int midis = nodenum;
 69                      for(i = head[u];i != -1;i = E[i].next) {
 70                             v = E[i].t;
 71                             if(E[i].val && midis > dis[v]) {
 72                                    cur[u] = i;
 73                                    midis = dis[v];
 74                             }
 75                      }
 76                      if( (-- gap[ dis[u] ]) == 0 ) break;
 77                      gap[ dis[u] = midis + 1 ] ++;
 78                      u = pre[u];
 79               }
 80               return maxflow;
 81        }
 82        inline void insert(int u,int v,int c,int cc = 0) {
 83               E[node] = edge(u,v,c,head[u]);
 84               head[u] = node ++;
 85               E[node] = edge(v,u,cc,head[v]);
 86               head[v] = node ++;
 87        }
 88 }G;
 89 
 90 
 91 int main() {
 92     int t;
 93     scanf("%d",&t);
 94     while (t--) {
 95         int n,m;
 96         scanf("%d%d",&m,&n);
 97         n++;
 98         char s[5];
 99         G.init(m+1);
100         for(int i=1; i<=m; i++)
101         {
102             int c;
103             scanf("%s%d",s,&c);
104             if ('I' == s[0])
105                 G.insert(0,i,I);
106 
107             for(int j=0; j<c; j++)
108             {
109                 int num;
110                 scanf("%d",&num);
111                 num++;
112                 G.insert(num,i,1);
113                 G.insert(i,num,I);
114             }
115         }
116         m++;
117         int ans = G.sap(0,n);
118         if (ans >= I)
119             printf("PANIC ROOM BREACH\n");
120         else
121             printf ("%d\n", ans );
122     }
123     return 0;
124 }

 

posted @ 2014-04-19 22:22  辛力啤  阅读(247)  评论(0编辑  收藏  举报