根据题意 要求锁一些门 使得入侵者无法到达指定的房间 这个是不是很像网络流当中的最小割 即把图中所有点分成 S T 两个集合 使得满流后不再连通 而最小割是网络流当中容量最小的割 这恰好又满足题目所求锁最少门的限定
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 30;
const int INF = 1e7;
struct Edge{
int u, v, cap, flow;
Edge(){}
Edge(int u, int v, int cap, int flow):u(u), v(v), cap(cap), flow(flow){}
};
struct ISAP{
int n, s, t;
int cur[maxn], d[maxn], p[maxn], num[maxn];
vector<int> G[maxn];
vector<Edge> edges;
void init(int n){
this -> n = n;
for(int i= 0; i < n; i++) G[i].clear();
edges.clear();
}
void add(int u, int v, int cap){
edges.push_back(Edge(u, v, cap, 0));
edges.push_back(Edge(v, u, 0, 0));
int m = edges.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
}
void bfs(){
for(int i = 0; i< n; i++) d[i] = INF;
d[t] = 0;
queue<int> Q;
Q.push(t);
while(!Q.empty()){
int x = Q.front(); Q.pop();
for(int i = 0; i < G[x].size(); i++){
Edge &e = edges[G[x][i]];
if(e.cap > 0 || d[e.v] <= d[x] + 1) continue;
d[e.v] = d[x] + 1;
Q.push(e.v);
}
}
}
int augment(){
int x = t, a = INF;
while(x != s){
Edge &e = edges[p[x]];
a = min(a, e.cap - e.flow);
x = e.u;
}
x = t;
while(x != s){
edges[p[x]].flow += a;
edges[p[x]^1].flow -= a;
x = edges[p[x]].u;
}
return a;
}
int maxflow(int s, int t){
this -> s = s;
this -> t = t;
memset(cur, 0, sizeof(cur));
memset(num, 0, sizeof(num));
bfs();
for(int i = 0; i< n; i++)if(d[i] != INF) num[d[i]]++;
int x = s, flow = 0;
while(d[s] < n){
if(x == t){
flow += augment();
x = s;
}
int ok = 0;
for(int i = cur[x]; i < G[x].size(); i++){
Edge &e = edges[G[x][i]];
if(e.cap > e.flow && d[e.v] + 1 == d[x]){
ok = 1;
cur[x] = i;
p[e.v] = G[x][i];
x = e.v;
break;
}
}
if(!ok){
int m = n - 1;
for(int i = 0; i < G[x].size(); i++){
Edge &e = edges[G[x][i]];
if(e.cap > e.flow) m = min(m, d[e.v]);
}
if(--num[d[x]] == 0) break;
++num[d[x] = m + 1];
cur[x] = 0;
if(x != s) x = edges[p[x]].u;
}
}
return flow;
}
}solver;
void solve(){
int n, m, x, S, T;
char s[3];
scanf("%d%d", &n, &T);
S = n;
solver.init(n + 1);
for(int i = 0; i < n; i++){
scanf("%s%d", s, &m);
if(s[0] == 'I') solver.add(S, i, INF);
for(int j = 0; j < m; j++){
scanf("%d", &x);
solver.add(i, x, INF);
solver.add(x, i, 1);
}
}
int ans = solver.maxflow(S, T);
if(ans < INF) printf("%d\n", ans);
else printf("PANIC ROOM BREACH\n");
}
int main()
{
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--){
solve();
}
return 0;
}