POJ 3084 最大流

来源:互联网 发布:单片机多功能调试 编辑:程序博客网 时间:2024/06/05 16:32
Panic Room
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 1592 Accepted: 789

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.

Sample Input

37 2NI 0I 3 0 4 5NI 2 1 6NI 2 1 2NI 0NI 0NI 07 2I 0NI 3 0 4 5NI 2 1 6I 2 1 2NI 0NI 0NI 04 3I 0NI 1 2NI 1 0NI 4 1 1 2 2

Sample Output

2PANIC ROOM BREACH1

Source

South Central USA 2006
 
 
以房间为节点,
对于每扇门,从开关一侧到另一侧容量为INF,反向容量为1,如果两个房间间有多扇门,则容量累加
对于有入侵者的房间,从源点边INF的容量,以要保护的房间为汇点,求最大流
 
 
#include<iostream>#include<cstring>#include<cstdio>using namespace std;int m,n;#define INF 0x1f1f1f1f#define MIN(a,b) ((a)<(b)?(a):(b))#define MAX(a,b) ((a)>(b)?(a):(b))#define SIZE 30int flow[SIZE][SIZE];int cap[SIZE][SIZE];int lev[SIZE];int mn[SIZE];int que[100000];//BSF找层次网络,一次寻找多条增广路径//st最小顶点标号,ed最大顶点标号,src源点标号,tar汇点标号bool bfs(int st,int ed,int src,int tar){    memset(lev,0x1f,sizeof(lev));    int front;    int rear;    front=rear=0;    que[front++]=src;    lev[src]=0;    while(rear<front)    {        int t=que[rear];        rear++;        for(int i=st;i<=ed;i++)        {            if(cap[t][i]>flow[t][i])            {                if(lev[t]+1<lev[i])                {                    lev[i]=lev[t]+1;                    que[front++]=i;                }            }        }    }    return lev[tar]<INF;}//利用层次网络进行增广,每次DFS寻找的是从该节点出发进行DFS增加的总流量//mn表示从源点至该节点可增广流量int dfs(int v,int st,int ed,int src,int tar){    int ret=0;    if(v==tar)return mn[tar];    for(int i=st;i<=ed;i++)    {        if(mn[v]==0)break;        if(cap[v][i]>flow[v][i]&&lev[v]+1==lev[i])        {            mn[i]=MIN(mn[v],cap[v][i]-flow[v][i]);            int tt=dfs(i,st,ed,src,tar);            ret+=tt;            mn[v]-=tt;//每次修改mn[v]            flow[v][i]+=tt;            flow[i][v]-=tt;        }    }    if(ret==0)    {        lev[v]=INF;    }    return ret;}int dinic(int st,int ed,int src,int tar){    int ret=0;    while(bfs(st,ed,src,tar))//存在可增广路    {        memset(mn,0x1f,sizeof(mn));        int r=dfs(src,st,ed,src,tar);        if(r==0)break;        ret+=r;    }    return ret;}int main(){    //printf("%d\n",INF);    int t;    scanf("%d",&t);    while(t--)    {        memset(flow,0,sizeof(flow));        memset(cap,0,sizeof(cap));        scanf("%d%d",&m,&n);        for(int i=0;i<m;i++)        {            char ch[5];            int c;            scanf("%s%d",ch,&c);            if(strcmp(ch,"I")==0)            {                cap[m][i]=INF;            }            for(int j=0;j<c;j++)            {                int num;                scanf("%d",&num);                cap[i][num]=INF;                if(cap[num][i]<INF)                {                    cap[num][i]++;                }            }        }        int res=dinic(0,m,m,n);        if(res<INF)printf("%d\n",res);        else printf("PANIC ROOM BREACH\n");    }    return 0;}

原创粉丝点击