【
题意】理解了半天……大意就是,有一些房间,初始时某些房间之间有一些门,并且这些门是打开的,也就是可以来回走动的,但是这些门是确切属于某个房间的,也就是说如果要锁门,则只有在那个房间里才能锁。 现在一些房间里有一些恐怖分子,要搞破坏,但是现在有个房间很重要,不能被他们破坏,这就需要锁一部分的门,不让恐怖分子有可趁之机,求最少需要锁多少个门。
【
建图】
这个一看就能联想到最小割……但是建图还是需要注意一些地方。从恐怖分子到重要房间我们就能联想到s->t流,所以建一个源点连接所有恐怖分子所在房间,然后汇点便是那个保护的房间。然后需要处理边了~
对于每个门的描述(u, v),其中u可以控制锁的开关,也就是说恐怖分子从u是一定能够走到v的,这条边不能被割,所以我们连一条(u, v, oo)的边,同时,如果恐怖分子从v往u走,那么我们可以锁门,所以再连一条(v, u, 1)的边~然后求最小割就好~如果最小割oo则输出PANIC ROOM BREACH。
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)/2)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXV = 50;
const int MAXE = 2005;
const int oo = 0x3fffffff;
/* Dinic-2.0-2013.07.21: adds template. double & int 转换方便多了,也不易出错 ~*/
template
struct Dinic{
struct node{
int u, v;
T flow;
int opp;
int next;
}arc[2*MAXE];
int vn, en, head[MAXV];
int cur[MAXV];
int q[MAXV];
int path[2*MAXE], top;
int dep[MAXV];
void init(int n){
vn = n;
en = 0;
mem(head, -1);
}
void insert_flow(int u, int v, T flow){
arc[en].u = u;
arc[en].v = v;
arc[en].flow = flow;
arc[en].next = head[u];
head[u] = en ++;
arc[en].u = v;
arc[en].v = u;
arc[en].flow = 0;
arc[en].next = head[v];
head[v] = en ++;
}
bool bfs(int s, int t){
mem(dep, -1);
int lq = 0, rq = 1;
dep[s] = 0;
q[lq] = s;
while(lq < rq){
int u = q[lq ++];
if (u == t){
return true;
}
for (int i = head[u]; i != -1; i = arc[i].next){
int v = arc[i].v;
if (dep[v] == -1 && arc[i].flow > 0){
dep[v] = dep[u] + 1;
q[rq ++] = v;
}
}
}
return false;
}
T solve(int s, int t){
T maxflow = 0;
while(bfs(s, t)){
int i, j;
for (i = 1; i <= vn; i ++) cur[i] = head[i];
for (i = s, top = 0;;){
if (i == t){
int mink;
T minflow = 0x7fffffff; //要比容量的oo大
for (int k = 0; k < top; k ++)
if (minflow > arc[path[k]].flow){
minflow = arc[path[k]].flow;
mink = k;
}
for (int k = 0; k < top; k ++)
arc[path[k]].flow -= minflow, arc[path[k]^1].flow += minflow;
maxflow += minflow;
top = mink;
i = arc[path[top]].u;
}
for (j = cur[i]; j != -1; cur[i] = j = arc[j].next){
int v = arc[j].v;
if (arc[j].flow && dep[v] == dep[i] + 1)
break;
}
if (j != -1){
path[top ++] = j;
i = arc[j].v;
}
else{
if (top == 0) break;
dep[i] = -1;
i = arc[path[-- top]].u;
}
}
}
return maxflow;
}
};
Dinic dinic;
int main(){
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
int t;
scanf("%d", &t);
while(t --){
int n, m;
scanf("%d %d", &n, &m);
m ++;
dinic.init(n+1);
int sum = 0;
for (int i = 1; i <= n; i ++){
char str[5];
int num;
scanf("%s %d", str, &num);
sum += num;
if (str[0] == 'I'){
dinic.insert_flow(n+1, i, oo);
}
for (int j = 0; j < num; j ++){
int tmp;
scanf("%d", &tmp);
dinic.insert_flow(i, tmp+1, oo);
dinic.insert_flow(tmp+1, i, 1);
}
}
int res = dinic.solve(n+1, m);
if (res > sum){
puts("PANIC ROOM BREACH");
}
else{
printf("%d
", res);
}
}
return 0;
}