Sicily 1402. Panic Room

1402. Panic Room

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

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: 
Sicily 1402. Panic Room - Night -  
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 –  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 –  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.

Sample Input

3
7 2
NI 0
I 3 0 4 5
NI 2 1 6
NI 2 1 2
NI 0
NI 0
NI 0
7 2
I 0
NI 3 0 4 5
NI 2 1 6
I 2 1 2
NI 0
NI 0
NI 0
4 3
I 0
NI 1 2
NI 1 0
NI 4 1 1 2 2

Sample Output

2
PANIC ROOM BREACH
1
// Problem#: 1402
// Submission#: 2991966
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <algorithm>
#include <iostream>
#include <string>
#include <stdio.h>
#include <queue>
#include <string.h>
#include <vector>
#include <iomanip>
#include <map>
#include <stack>
#include <functional>
#include <list>
using namespace std;

#define MAX_POINT 30
#define INF 99999999

struct edge {
    int to;
    int cap;
    int rev;
    edge() {}
    edge(int tto, int ccap, int rrev) {

        to = tto;
        cap = ccap;
        rev = rrev;

    }
};

bool vis[MAX_POINT];
int points;
vector<edge> G[MAX_POINT];

void addEdge(int from, int to, int cap) {

    G[from].push_back(edge(to, cap, G[to].size()));
    G[to].push_back(edge(from, 0, G[from].size() - 1));

}

int makeSuperStart(vector<int> start) {

    if (start.size() == 1) return start[0];

    int s = points;
    points++;

    for (int i = 0; i < start.size(); i++) {

        addEdge(s, start[i], INF);
        addEdge(start[i], s, INF);

    }

    return s;

}

int makeSuperEnd(vector<int> end) {

    if (end.size() == 1) return end[0];

    int e = points;
    points++;

    for (int i = 0; i < end.size(); i++) {

        addEdge(end[i], e, INF);
        addEdge(e, end[i], INF);

    }

    return e;

}

int dfs(int from, int to, int lastCap) {

    if (from == to) return lastCap;

    vis[from] = true;

    for (int i = 0; i < G[from].size(); i++) {

        edge & e = G[from][i];

        if (!vis[e.to] && e.cap > 0) {

            int nextFlow = dfs(e.to, to, min(lastCap, e.cap));

            if (nextFlow > 0) {
            
                e.cap -= nextFlow;
                G[e.to][e.rev].cap += nextFlow;
                return nextFlow;

            }

        }

    }

    return 0;

}

int MaxFlow(vector<int> start, vector<int> end) {

    int maxFlow = 0;

    int s = makeSuperStart(start);
    int e = makeSuperEnd(end);

    while (1) {

        memset(vis, false, sizeof(vis));

        int f = dfs(s, e, INF);

        if (f == 0) return maxFlow;

        maxFlow += f;

    }

    return maxFlow;

}

int main() {

    std::ios::sync_with_stdio(false);

    int caseNum;

    cin >> caseNum;

    while (caseNum--) {

        int n, p;
        vector<int> start, end;

        cin >> n >> p;

        end.push_back(p);

        //reset
        for (int i = 0; i < MAX_POINT; i++) G[i].clear();
        points = n;
        //reset

        for (int i = 0; i < n; i++) {

            string s;
            int m;

            cin >> s >> m;

            if (s == "I") {

                start.push_back(i);

            }

            for (int j = 0; j < m; j++) {

                int to;

                cin >> to;

                addEdge(i, to, INF);
                addEdge(to, i, 1);

            }

        }

        int ans = MaxFlow(start, end);

        if (ans >= INF) cout << "PANIC ROOM BREACH" << endl;
        else cout << ans << endl;

    }

    //getchar();
    //getchar();
    return 0;
}            


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值