zoj 2788 Panic Room (最小割)

来源:互联网 发布:软件质量保证的过程 编辑:程序博客网 时间:2024/05/16 15:00

题意:

有n个房间,已知一个要保护的房间编号。每个房间可能向另外的房间有门,但是

门只能从某一面打开。现在某些房间有入侵者,如果要防止入侵者进入要保护的房间

至少要看好多少扇门。


算法:

Dinic求最小割,关键在建图。

由于可能有多个房间有入侵者,所以建一个超级源点。出于习惯,我对应地也建了一个超级汇点。

源点与所有有入侵者进入的房间连INF的边,要保护的房间与汇点之间连INF的边。这样跑最大流时

就能保证这些边不断掉。

如果有一扇门连通A和B,把手在房间A,则从A到B连INF的边,从B到A连边长为1的边。


如果有入侵者的房间和要保护的房间直接相连,且门把手在入侵者的房间则永远无法阻止入侵者进入要

保护的房间。


#include<cstdio>#include<iostream>#include<cstring>#define maxm 410#define maxn 30#define INF 0x3f3f3f3fusing namespace std;struct node{    int to,v,next;}e[maxm<<2];int head[maxn],cnt,q[maxn],d[maxn];int st,en,n,flag;void add(int x,int y,int z){    e[cnt].to = y;    e[cnt].v = z;    e[cnt].next = head[x];    head[x] = cnt++;    e[cnt].to = x;    e[cnt].v = 0;    e[cnt].next = head[y];    head[y] = cnt++;}void init(){    memset(head,-1,sizeof(head));    cnt = 0;    st = n;    en = n+1;    flag = 0;}bool bfs(){    memset(d,-1,sizeof(d));    int f = 0,r = 0,u;    q[r++] = st;    d[st] = 0;    while(f<r)    {        u = q[f++];        for(int i=head[u];i!=-1;i=e[i].next)        {            int t = e[i].to;            if(e[i].v>0 && d[t]==-1)//>0            {                d[t] = d[u]+1;                q[r++] = t;                if(t==en) return true;            }        }    }    return false;}int dfs(int x,int flow){    if(x==en) return flow;    int ret = 0,dd;    for(int i=head[x];ret<flow && i!=-1;i=e[i].next)    {        int t = e[i].to;        if(d[t] == d[x]+1 && e[i].v)        {            dd = dfs(t,min(flow,e[i].v));            e[i].v-=dd;            e[i^1].v+=dd;            flow-=dd;            ret+=dd;        }    }    if(!ret) d[x]=-1;    return ret;}int Dinic(){    int tmp = 0,maxflow = 0;    while(bfs())    {        while(tmp=dfs(st,INF))            maxflow+=tmp;    }    return maxflow;}int main(){    int T,x,num,y;    char sig[5];    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&x);        init();        for(int i=0;i<n;i++)        {            scanf("%s%d",sig,&num);            if(i==x)                add(i,en,INF);            if(sig[0]=='N')            {                if(num==0)                    continue;                else                {                    for(int j=0;j<num;j++)                    {                        scanf("%d",&y);                        add(y,i,1);                        add(i,y,INF);                    }                }            }            else            {                add(st,i,INF);                if(num==0) continue;                else                {                    for(int j=0;j<num;j++)                    {                        scanf("%d",&y);                        if(y==x) flag = 1;                        add(i,y,INF);                        add(y,i,1);                    }                }            }        }        if(flag) printf("PANIC ROOM BREACH\n");        else printf("%d\n",Dinic());    }    return 0;}


0 0