zoukankan      html  css  js  c++  java
  • POJ 3084 Panic Room(最大流最小割)

    Description

    You are the lead programmer for the Securitron 9042, the latest and greatest in home security software from Jellern Inc. (Motto: We secure your stuff so YOU can't even get to it). The software is designed to "secure" a room; it does this by determining the minimum number of locks it has to perform to prevent access to a given room from one or more other rooms. Each door connects two rooms and has a single control panel that will unlock it. This control panel is accessible from only one side of the door. So, for example, if the layout of a house looked like this:    with rooms numbered 0-6 and control panels marked with the letters "CP" (each next to the door it can unlock and in the room that it is accessible from), then one could say that the minimum number of locks to perform to secure room 2 from room 1 is two; one has to lock the door between room 2 and room 1 and the door between room 3 and room 1. Note that it is impossible to secure room 2 from room 3, since one would always be able to use the control panel in room 3 that unlocks the door between room 3 and room 2. 

    Input

    Input to this problem will begin with a line containing a single integer x indicating the number of datasets. Each data set consists of two components:
    1. Start line – a single line "m n" (1 <=m<= 20; 0 <=n<= 19) where m indicates the number of rooms in the house and n indicates the room to secure (the panic room).
    2. Room list – a series of m lines. Each line lists, for a single room, whether there is an intruder in that room ("I" for intruder, "NI" for no intruder), a count of doors c (0 <= c <= 20) that lead to other rooms and have a control panel in this room, and a list of rooms that those doors lead to. For example, if room 3 had no intruder, and doors to rooms 1 and 2, and each of those doors' control panels were accessible from room 3 (as is the case in the above layout), the line for room 3 would read "NI 2 1 2". The first line in the list represents room 0. The second line represents room 1, and so on until the last line, which represents room m - 1. On each line, the rooms are always listed in ascending order. It is possible for rooms to be connected by multiple doors and for there to be more than one intruder!

    Output

    For each dataset, output the fewest number of locks to perform to secure the panic room from all the intruders. If it is impossible to secure the panic room from all the intruders, output "PANIC ROOM BREACH". Assume that all doors start out unlocked and there will not be an intruder in the panic room.

    题目大意:有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
    ", 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
    ", ans);
    113     }
    114 }
    View Code
  • 相关阅读:
    Windows 10 IoT Serials 3
    Guest Speaker on 2015 WinHEC Shenzhen 秋季大会
    Ignite China 2015 之行
    Windows 10 IoT Serials 2
    Build 2015 Beijing & Windows 10 China Geek Challenge
    Windows 10 IoT Serials 1
    WinHEC 2015 深圳之行
    Windows on Device 项目实践 5
    2015 MVP OpenDay 及 Community Camp 演讲PPT分享
    Windows on Device 项目实践 4
  • 原文地址:https://www.cnblogs.com/oyking/p/3247151.html
Copyright © 2011-2022 走看看