首页 > 其他分享 >BZOJ 1189([HNOI2007]紧急疏散evacuate-网络流二分+拆点)

BZOJ 1189([HNOI2007]紧急疏散evacuate-网络流二分+拆点)

时间:2022-10-24 19:35:37浏览次数:73  
标签:return 1189 int 拆点 long MAXN evacuate sz1 define


发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是’.’,那么表示这是一块空地;如果是’X’,那么表示这是一面墙,如果是’D’,那么表示这是一扇门,人们可以从这儿撤出房间。已知门一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本不可能。

Input

输入文件第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,以下N行M列描述一个N M的矩阵。其中的元素可为字符’.’、’X’和’D’,且字符间无空格。

Output

只有一个整数K,表示让所有人安全撤离的最短时间,如果不可能撤离,那么输出’impossible’(不包括引号)。

Sample Input

5 5

XXXXX

X…D

XX.XX

X..XX

XXDXX
Sample Output

3
HINT

2015.1.12新加数据一组,鸣谢1756500824

C++语言请用scanf(“%s”,s)读入!

BFS计算出每个人离每个出口的距离,网络流,二分+拆点,注意一个人不能路过一个出口到达另一个出口(因为出口格子有人数限制)d。

#include<cstdio>
#include<queue>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define pi pair<int,int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (400+400*800+100)
#define MAXM (6000000+100)
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
class Max_flow //dinic+µ±Ç°»¡ÓÅ»¯
{
public:
int n,t;
int q[MAXN];
int edge[MAXM],Next[MAXM],Pre[MAXN],weight[MAXM],size;
void addedge(int u,int v,int w)
{
edge[++size]=v;
weight[size]=w;
Next[size]=Pre[u];
Pre[u]=size;
}
void addedge2(int u,int v,int w){addedge(u,v,w),addedge(v,u,0);}
bool b[MAXN];
int d[MAXN];
bool SPFA(int s,int t)
{
For(i,n) d[i]=INF;
MEM(b)
d[q[1]=s]=0;b[s]=1;
int head=1,tail=1;
while (head<=tail)
{
int now=q[head++];
Forp(now)
{
int &v=edge[p];
if (weight[p]&&!b[v])
{
d[v]=d[now]+1;
b[v]=1,q[++tail]=v;
}
}
}
return b[t];
}
int iter[MAXN];
int dfs(int x,int f)
{
if (x==t) return f;
Forpiter(x)
{
int v=edge[p];
if (weight[p]&&d[x]<d[v])
{
int nowflow=dfs(v,min(weight[p],f));
if (nowflow)
{
weight[p]-=nowflow;
weight[p^1]+=nowflow;
return nowflow;
}
}
}
return 0;
}
int max_flow(int s,int t)
{
(*this).t=t;
int flow=0;
while(SPFA(s,t))
{
For(i,n) iter[i]=Pre[i];
int f;
while (f=dfs(s,INF))
flow+=f;
}
return flow;
}
void mem(int n)
{
(*this).n=n;
size=1;
MEM(Pre)
}
}S;

#undef MAXN
#define MAXN (30)

char s[MAXN][MAXN];
int h[MAXN][MAXN]={0};

const int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
int dis[450][450];
int n,m;
bool inside(int i,int j) {return 1<=i&&i<=n&&1<=j&&j<=m&&s[i][j]!='X'; }
int id(int i,int j){return i*m-m+j;}
void bfs(int i,int j) {
int st=id(i,j);
dis[st][st]=0;
queue q;
q.push(mp(i,j));
while(!q.empty()) {
pi now=q.front(); q.pop();
int x=now.fi,y=now.se;
Rep(di,4) {
int nx=x+dir[di][0],ny=y+dir[di][1];
if (inside(nx,ny)&&dis[st][id(nx,ny)]==INF) {
dis[st][id(nx,ny)]=dis[st][id(x,y)]+1;
if (s[nx][ny]!='D') q.push(mp(nx,ny));
}
}
}
}
#define vi vector<int>
#define SI(x) ((x).size())
vi v1,v2;
int sz1,sz2;
void prework() {
For(i,n) For(j,m)
if (s[i][j]=='.') v1.pb(id(i,j));
else if (s[i][j]=='D') v2.pb(id(i,j));
sz1=SI(v1);sz2=SI(v2);
}
int check(int t) {
S.mem(sz1+sz2*t+2);
int tot2=sz1+sz2*t,st=tot2+1,ed=st+1;

For(i,sz1) S.addedge2(st,i,1);
Fork(i,sz1+1,tot2) S.addedge2(i,ed,1);

For(i,sz1) For(j,sz2) if (dis[v1[i-1]][v2[j-1]]<=t) {
S.addedge2(i,sz1+t*(j-1)+dis[v1[i-1]][v2[j-1]],1);
}
For(i,sz2) {
For(d,t-1) {
S.addedge2(sz1+t*(i-1)+d,sz1+t*(i-1)+d+1,sz1);
}
}
int ans=S.max_flow(st,ed);
return ans;
}
int main()
{
// freopen("bzoj1189.in","r",stdin);
// freopen(".out","w",stdout);
cin>>n>>m;
For(i,n) scanf("%s",s[i]+1);
int p=0;
For(i,n) For(j,m) if (s[i][j]=='D') {
h[i][j]=++p;
}
int cnt=0;
MEMI(dis)
For(i,n) For(j,m) if (s[i][j]=='.') {
++cnt,bfs(i,j);
}
int l=0,r=2*n*m,ans=INF;
prework();
while(l<=r) {
int m=l+r>>1;
if (check(m)==cnt) ans=m,r=m-1;else l=m+1;
}

if (ans==INF) puts("impossible"); else printf("%d\n",ans);
return 0;
}


标签:return,1189,int,拆点,long,MAXN,evacuate,sz1,define
From: https://blog.51cto.com/u_15724837/5791031

相关文章

  • [HNOI2007]紧急疏散EVACUATE
    题目传送门:[HNOI2007]紧急疏散EVACUATEbfs+二分+最大流#include<queue>#include<string>#include<cstdio>#include<cstring>#include<algorithm>constintN=2......
  • Qt-Qt在开发过程中提示“报错C1189 No Target Architecture”
    相关资料:https://blog.csdn.net/wcc27857285/article/details/85197877 问题现象:有个启动外部bat文件的工程,今天突然想再建个相同功能的工程。代码如“WinExec("D:/a.b......
  • NC51189 Mondriaan's Dream
    题目链接题目题目描述SquaresandrectanglesfascinatedthefamousDutchpainterPietMondriaan.Onenight,afterproducingthedrawingsinhis'toiletseries......