您的位置:首页 > 其它

sicily 1402Panic Room(最大流最小割)

2011-02-27 10:59 260 查看
View Code

设置超级源点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
) 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: