zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    centos 安装 TortoiseSVN svn 客户端
    linux 定时任务 日志记录
    centos6.5 安装PHP7.0支持nginx
    linux root 用户 定时任务添加
    composer 一些使用说明
    laravel cookie写入
    laravel composer 安装指定版本以及基本的配置
    mysql 删除重复记录语句
    linux php redis 扩展安装
    linux php 安装 memcache 扩展
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3416869.html
Copyright © 2011-2022 走看看