[Sicily]1402. Panic Room(week 16)

来源:互联网 发布:卖淘宝小号的平台 编辑:程序博客网 时间:2024/06/05 18:56
设置超级源点s(此处标号为m的房间就是源点),如果房间k有入侵者(intruder),则存在一条有s指向k的弧,且容量为c(s,k)=INF;然后是处理由门联通的两个房间的关系了。(1)如果房间i和j有门且cp在i,则c(i,j)=INF,c(j,i)=1;(2)如果房间i和j有门且cp在j,则c(i,j)=1,c(j,i)=INF;超级汇点t就是要保护的房间号码。计算从s到t的最大流ans.若ans>=INF,说明无法保护,否则ans为需要锁上的门的最小数量。#include <iostream>#include <cstring>#include <string>#include <queue>#include <cstdio>using namespace std;const int MAX = 25;const int INF = 2000;int map[MAX][MAX],m,n,t,pre[MAX];bool vis[MAX];int Maxflow(){    int ans = 0;    while(true)    {        memset(vis,false,sizeof(vis));        memset(pre,0,sizeof(pre));        queue<int> q;    q.push(m); vis[m] = true;        while(!q.empty())        {            int cur = q.front(); q.pop();            if(cur == n) break;            for(int i = 0;i < m;++i)            {                if(!vis[i] && map[cur][i])                {                    vis[i] = true;    q.push(i); pre[i] = cur;                }            }        }        if(!vis[n]) break;        int Min = INF,u;        for( u = n;u != m;u = pre[u])        {            if(Min > map[pre[u]][u]) Min = map[pre[u]][u];        }        for(u = n;u != m;u = pre[u])        {            map[pre[u]][u] -= Min;            map[u][pre[u]] += Min;        }        ans += Min;    }    return ans;}int main(){    int i,lead_to,room; string is_intr;    scanf("%d",&t);    while(t--)    {        memset(map,0,sizeof(map));        scanf("%d %d",&m,&n);        for(i = 0;i < m;++i)        {            cin>>is_intr>>lead_to;            if(is_intr == "I")  map[m][i] = INF;             while(lead_to--)            {                scanf("%d",&room); map[i][room] = INF; map[room][i]++;            }        }        int ans = Maxflow();        if(ans >= INF ) cout<<"PANIC ROOM BREACH"<<endl;        else cout<<ans<<endl;        }    return 0;}