Description
Input
Output
题目大意:有n个房间,若干扇门,门是单向的,只能从一边上锁(如一道门连接a→b,任何时刻都能从a走到b,但上了锁之后就不能从b走到a了)。现在有些坏蛋入侵了一些房间,你不想让他们来到你的房间,问最少要锁上多少扇门,若全锁上都木有用……就……
思路:新建一个源点S,从S到坏蛋们入侵的房间连一条容量为无穷大的边,对每扇门a→b,连一条边a→b容量为无穷大,连b→a容量为1。若最大流≥无穷大(我是增广到一条容量为无穷大的路径直接退出),则无解(死定啦死定啦),否则最大流为答案。实则为求最小割,好像不需要解释了挺好理解的……
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 using namespace std; 6 7 const int MAXN = 25; 8 const int MAXE = 3010; 9 const int INF = 0x3fff3fff; 10 11 struct SAP { 12 int head[MAXN], dis[MAXN], pre[MAXN], cur[MAXN], gap[MAXN]; 13 int to[MAXE], next[MAXE], flow[MAXE]; 14 int n, st, ed, ecnt; 15 16 void init() { 17 memset(head, 0, sizeof(head)); 18 ecnt = 2; 19 } 20 21 void add_edge(int u, int v, int c) { 22 to[ecnt] = v; flow[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++; 23 to[ecnt] = u; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++; 24 //printf("%d->%d flow = %d\n", u, v, c); 25 } 26 27 void bfs() { 28 memset(dis, 0x3f, sizeof(dis)); 29 queue<int> que; que.push(ed); 30 dis[ed] = 0; 31 while(!que.empty()) { 32 int u = que.front(); que.pop(); 33 ++gap[dis[u]]; 34 for(int p = head[u]; p; p = next[p]) { 35 int &v = to[p]; 36 if(flow[p ^ 1] && dis[v] > n) { 37 dis[v] = dis[u] + 1; 38 que.push(v); 39 } 40 } 41 } 42 } 43 44 int Max_flow(int ss, int tt, int nn) { 45 st = ss; ed = tt; n = nn; 46 int ans = 0, minFlow = INF, u; 47 for(int i = 0; i <= n; ++i) { 48 cur[i] = head[i]; 49 gap[i] = 0; 50 } 51 u = pre[st] = st; 52 bfs(); 53 while(dis[st] < n) { 54 bool flag = false; 55 for(int &p = cur[u]; p; p = next[p]) { 56 int &v = to[p]; 57 if(flow[p] && dis[u] == dis[v] + 1) { 58 flag = true; 59 minFlow = min(minFlow, flow[p]); 60 pre[v] = u; 61 u = v; 62 if(u == ed) { 63 if(minFlow == INF) return INF;//no ans 64 ans += minFlow; 65 while(u != st) { 66 u = pre[u]; 67 flow[cur[u]] -= minFlow; 68 flow[cur[u] ^ 1] += minFlow; 69 } 70 minFlow = INF; 71 } 72 break; 73 } 74 } 75 if(flag) continue; 76 int minDis = n - 1; 77 for(int p = head[u]; p; p = next[p]) { 78 int &v = to[p]; 79 if(flow[p] && minDis > dis[v]) { 80 minDis = dis[v]; 81 cur[u] = p; 82 } 83 } 84 if(--gap[dis[u]] == 0) break; 85 gap[dis[u] = minDis + 1]++; 86 u = pre[u]; 87 } 88 return ans; 89 } 90 } G; 91 92 char s[5]; 93 int n, ss, tt, T, c, x; 94 95 int main() { 96 scanf("%d", &T); 97 while(T--) { 98 scanf("%d%d", &n, &tt); 99 ss = n; 100 G.init(); 101 for(int i = 0; i < n; ++i) { 102 scanf("%s%d", s, &c); 103 while(c--) { 104 scanf("%d", &x); 105 G.add_edge(i, x, INF); 106 G.add_edge(x, i, 1); 107 } 108 if(s[0] == 'I') G.add_edge(ss, i, INF); 109 } 110 int ans = G.Max_flow(ss, tt, ss); 111 if(ans == INF) puts("PANIC ROOM BREACH"); 112 else printf("%d\n", ans); 113 } 114 }