POJ 3084 Panic Room
这个题的题意不怎么好理解,关键是英语句子有点别扭。。题意:给你几个屋子,其中有些是恐怖者的屋子,有一个是需要保护的屋子,题目要求是不让恐怖者来到受保护的屋子。刚开始所有的门是打开的,让你求出最少需要关闭多少门,才能保证恐怖者不会到达目的地。
I 2 1 2 表示这个屋子是恐怖者,可以直接进入1房和2房。剩下的就是建图了,加一个源点,连边权为inf到所有的恐怖者的屋子,如果i->j,则从i连一条边权为INF到j,从j连一条边权为1的到i,可以证明,依靠最小割定理,求出最大流便是结果,如果最大流>=inf,则无解。
在求最大流时,因为ISAP()求cur_flow时,也用到了inf,结果造成了边权的冲突,错了很长时间.........,改成inf+1就OK了
code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
using namespace std;
#define MAXN 50
#define MAXE 10000
#define INF 0x3fffffff
int ne,nv,s,t,index,net[MAXN];
struct Edge{
int next,pair;
int v,flow,cap;
}edge[MAXE];
void add(const int& u,const int& v,const int& val,const int& val2)
{
edge[index].next = net[u];
net[u] = index;
edge[index].v = v;
edge[index].cap = val;
edge[index].flow = 0;
edge[index].pair = index + 1;
++index;
edge[index].next = net[v];
net[v] = index;
edge[index].v = u;
edge[index].cap = val2;
edge[index].flow = 0;
edge[index].pair = index - 1;
++index;
}
int ISAP()
{
int numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN];
int cur_flow,max_flow,u,tmp,neck,i;
memset(dist,0,sizeof(dist));
memset(numb,0,sizeof(numb));
for(i = 1 ; i <= nv ; ++i)
curedge[i] = net[i];
numb[nv] = nv;
max_flow = 0;
u = s;
while(dist[s] < nv){
if(u == t){
cur_flow = INF+1;
for(i = s; i != t;i = edge[curedge[i]].v)
if(cur_flow > edge[curedge[i]].cap){
neck = i;
cur_flow = edge[curedge[i]].cap;
}
for(i = s; i != t; i = edge[curedge[i]].v)
{
tmp = curedge[i];
edge[tmp].cap -= cur_flow;
edge[tmp].flow += cur_flow;
tmp = edge[tmp].pair;
edge[tmp].cap += cur_flow;
edge[tmp].flow -= cur_flow;
}
max_flow += cur_flow;
u = neck;
}
for(i = curedge[u]; i != -1; i = edge[i].next)
if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1)
break;
if(i != -1){
curedge[u] = i;
pre[edge[i].v] = u;
u = edge[i].v;
}else{
if(0 == --numb[dist[u]]) break;
curedge[u] = net[u];
for(tmp = nv,i = net[u]; i != -1; i = edge[i].next)
if(edge[i].cap > 0)
tmp = tmp<dist[edge[i].v]?tmp:dist[edge[i].v];
dist[u] = tmp + 1;
++numb[dist[u]];
if(u != s) u = pre[u];
}
}
return max_flow;
}
int main()
{
int i,j,tt,k,time,a,b,val,tmp,n;
char str[10];
scanf("%d",&time);
while(time--)
{
index = 0;
memset(net,-1,sizeof(net));
scanf("%d%d",&n,&t);
s = n + 1;
nv = s; ++t;
for(i = 1;i <= n; ++i)
{
scanf("%s %d",str,&k);
if(str[0] == 'I')
add(s,i,INF,0);
for(j = 1;j <= k; ++j)
{
scanf("%d",&a);
add(i,a+1,INF,1);
}
}
tmp = ISAP();
if(tmp>=INF)
printf("PANIC ROOM BREACH\n");
else
printf("%d\n",tmp);
}
return 0;
}
#include <cstdio>
#include <algorithm>
#include <memory.h>
using namespace std;
#define MAXN 50
#define MAXE 10000
#define INF 0x3fffffff
int ne,nv,s,t,index,net[MAXN];
struct Edge{
int next,pair;
int v,flow,cap;
}edge[MAXE];
void add(const int& u,const int& v,const int& val,const int& val2)
{
edge[index].next = net[u];
net[u] = index;
edge[index].v = v;
edge[index].cap = val;
edge[index].flow = 0;
edge[index].pair = index + 1;
++index;
edge[index].next = net[v];
net[v] = index;
edge[index].v = u;
edge[index].cap = val2;
edge[index].flow = 0;
edge[index].pair = index - 1;
++index;
}
int ISAP()
{
int numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN];
int cur_flow,max_flow,u,tmp,neck,i;
memset(dist,0,sizeof(dist));
memset(numb,0,sizeof(numb));
for(i = 1 ; i <= nv ; ++i)
curedge[i] = net[i];
numb[nv] = nv;
max_flow = 0;
u = s;
while(dist[s] < nv){
if(u == t){
cur_flow = INF+1;
for(i = s; i != t;i = edge[curedge[i]].v)
if(cur_flow > edge[curedge[i]].cap){
neck = i;
cur_flow = edge[curedge[i]].cap;
}
for(i = s; i != t; i = edge[curedge[i]].v)
{
tmp = curedge[i];
edge[tmp].cap -= cur_flow;
edge[tmp].flow += cur_flow;
tmp = edge[tmp].pair;
edge[tmp].cap += cur_flow;
edge[tmp].flow -= cur_flow;
}
max_flow += cur_flow;
u = neck;
}
for(i = curedge[u]; i != -1; i = edge[i].next)
if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1)
break;
if(i != -1){
curedge[u] = i;
pre[edge[i].v] = u;
u = edge[i].v;
}else{
if(0 == --numb[dist[u]]) break;
curedge[u] = net[u];
for(tmp = nv,i = net[u]; i != -1; i = edge[i].next)
if(edge[i].cap > 0)
tmp = tmp<dist[edge[i].v]?tmp:dist[edge[i].v];
dist[u] = tmp + 1;
++numb[dist[u]];
if(u != s) u = pre[u];
}
}
return max_flow;
}
int main()
{
int i,j,tt,k,time,a,b,val,tmp,n;
char str[10];
scanf("%d",&time);
while(time--)
{
index = 0;
memset(net,-1,sizeof(net));
scanf("%d%d",&n,&t);
s = n + 1;
nv = s; ++t;
for(i = 1;i <= n; ++i)
{
scanf("%s %d",str,&k);
if(str[0] == 'I')
add(s,i,INF,0);
for(j = 1;j <= k; ++j)
{
scanf("%d",&a);
add(i,a+1,INF,1);
}
}
tmp = ISAP();
if(tmp>=INF)
printf("PANIC ROOM BREACH\n");
else
printf("%d\n",tmp);
}
return 0;
}