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 }