POJ 3084 Panic Room

题意:有m个房间,你需要保护第n个房间使得其不被攻入。房间与房间之间会有门,门上有机关,因此当门关上时,只能从一边进入另外一边而不能从相反方向进入。现在告诉你这n个房间以及门的分布情况,以及开始的时候哪些房间里有贼,问至少关掉几个门使得房间n不被攻入。

感觉这个题目蛮有意思的。比较容易想到最小割。如果从房间a到房间b有一个门,如果这个门关上了,且门上的机关使得贼只能从a进入b而不能让其从b进入a,那么这里对应两条边(a,b,inf),(b,a,1),如果房间i里面有贼,对应边(S,i,inf),而需要保护的那个房间n就会汇点T。然后求一遍最大流。如果maxflow>=inf就说明不存在合法方案了,否则maxflow就是答案。而流的意思就是要关掉多少扇门了。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define maxn 25
 5 #define maxm 1000000
 6 #define INF 1<<20
 7 using namespace std;
 8 int v[maxm],next[maxm],w[maxm];
 9 int first[maxn],q[maxn],d[maxn],work[maxn];
10 int e,S,T;
11 
12 void init(){
13     e = 0;
14     memset(first,-1,sizeof(first));
15 }
16 
17 void add_edge(int a,int b,int c){
18     v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++;
19 }
20 
21 int bfs(){
22     int rear = 0;
23     memset(d,-1,sizeof(d));
24     d[S] = 0;q[rear++] = S;
25     for(int i = 0;i < rear;i++){
26         for(int j = first[q[i]];j != -1;j = next[j])
27             if(w[j] && d[v[j]] == -1){
28                 d[v[j]] = d[q[i]] + 1;
29                 q[rear++] = v[j];
30                 if(v[j] == T)   return 1;
31             }
32     }
33     return 0;
34 }
35 
36 int dfs(int cur,int a){
37     if(cur == T)    return a;
38     for(int &i = work[cur];i != -1;i = next[i]){
39         if(w[i] && d[v[i]] == d[cur] + 1)
40             if(int t = dfs(v[i],min(a,w[i]))){
41                 w[i] -= t;w[i^1] += t;
42                 return t;
43             }
44     }
45     return 0;
46 }
47 
48 int dinic(){
49     int ans = 0;
50     while(bfs()){
51         memcpy(work,first,sizeof(first));
52         ans += dfs(S,INF);
53     }
54     return ans;
55 }
56 
57 int main()
58 {
59     int kase,n;
60     char str[10];
61     scanf("%d",&kase);
62     while(kase--){
63         init();
64         scanf("%d%d",&n,&T);
65         S = n+1;
66         for(int i = 0;i < n;i++){
67             int c,num;
68             scanf("%s %d",str,&c);
69             if(str[0] == 'I'){
70                 add_edge(S,i,INF);
71                 add_edge(i,S,0);
72             }
73             while(c--){
74                 scanf("%d",&num);
75                 add_edge(i,num,INF);
76                 add_edge(num,i,1);
77             }
78         }
79         int ans = dinic();
80         if(ans >= INF)  printf("PANIC ROOM BREACH
");
81         else    printf("%d
",ans);
82     }
83     return 0;
84 }
View Code
原文地址:https://www.cnblogs.com/zhexipinnong/p/3416869.html