http://poj.org/problem?id=3084
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1379 | Accepted: 653 |
Description
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
- 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).
- 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
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
題意:n個房間,房間之間有門連接,對於一扇門只有在其中一個房間可以打開它,現在給你一個房間和若干個房間,問你最少要鎖上幾扇門使得這些房間與給定的房間隔絕。初始的時候所有門都是開着的。
對於連接兩個房間的門i,j。如果在i房間可以打開門則連邊map[i][j]=inf,map[j][i]=1;
最後處理重邊的情況。
#include<stdio.h>
#include<string.h>
#define N 50
const int inf=0x3f3f3f3f;
int map[N][N],dis[N],cnt[N];
int pre[N],now[N],low[N];
int sap(int n,int s,int t) //頂點爲0-n
{
int i,j,k,flow=inf,min,ans=0;
bool flag;
memset(dis,0,sizeof(dis));
memset(cnt,0,sizeof(cnt));
memset(pre,0,sizeof(pre));
for(i=0;i<=n;i++) now[i]=0;
cnt[0]=n+1;
i=s;
while(dis[s]<=n)
{
low[i]=flow;
flag=false;
for(j=now[i];j<=n;j++)
if(map[i][j]>0&&dis[i]==dis[j]+1)
{
now[i]=j;flag=true;
if(map[i][j]<flow) flow=map[i][j];
pre[j]=i;i=j;
if(i==t)
{
ans+=flow;
while(i!=s)
{
k=pre[i];
map[k][i]-=flow;
map[i][k]+=flow;
i=k;
}
flow=inf;
}
break;
}
if(flag) continue;
if(--cnt[dis[i]]==0) break;
for(min=n+1,j=0;j<=n;j++)
if(map[i][j]>0&&dis[j]<min)
{
min=dis[j];
now[i]=j;
}
dis[i]=min+1;
cnt[dis[i]]++;
if(i!=s) //修改頂標後回溯
{
i=pre[i];
flow=low[i];
}
}
return ans;
}
int main()
{
int tt,n,t,i,j,k,r;
char str[3];
scanf("%d",&tt);
while(tt--)
{
scanf("%d%d",&n,&t);
memset(map,0,sizeof(map));
for(i=0;i<n;i++)
{
scanf("%s%d",str,&k);
for(r=0;r<k;r++)
{
scanf("%d",&j);
map[i][j]=inf;
map[j][i]++;
}
if(str[0]=='I')
map[n][i]=inf;
}
int ans=sap(n,n,t);
if(ans>=inf)
printf("PANIC ROOM BREACH\n");
else
printf("%d\n",ans);
}
return 0;
}