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 }