bzoj1189 [HNOI2007]紧急疏散evacuate(二分答案+bfs+最大流判是否满流)
2017-11-23 16:29
387 查看
首先bfs处理出每个人到每个门所需的时间。然后二分答案,对于所有人能到的所有门,建边,边权为1,从源点向所有人建边,边权为1,从所有门向汇点建边,边权为mid(最多出去mid个人),dinic跑最大流看是否满流。
然后这是错的。考虑这样一个样例:
4 5
XXDXX
XX.XX
X…X
XXDXX
答案应该是3,而我们输出了2.原因就在于有一个门两人都只能在2及以后才能到。因此我们还得把每个门按时间拆成mid个门,分别建边。比如说x到D1的最小距离为s,则x->[D1][s],[D1][s+1]…[D1][s+2],边权为1.
然后这是错的。考虑这样一个样例:
4 5
XXDXX
XX.XX
X…X
XXDXX
答案应该是3,而我们输出了2.原因就在于有一个门两人都只能在2及以后才能到。因此我们还得把每个门按时间拆成mid个门,分别建边。比如说x到D1的最小距离为s,则x->[D1][s],[D1][s+1]…[D1][s+2],边权为1.
#include <bits/stdc++.h> using namespace std; #define ll long long #define N 40000 #define inf 0x3f3f3f3f #define pa pair<int,int> inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } int n,m,h ,num=1,lev ,a[100][400],tot=0,D=0,id[21][21],dis[21][21]; int dx[]={0,0,1,-1},dy[]={1,-1,0,0},ans=0,door[100][401],T; char mp[21][21]; struct edge{ int to,next,val; }data[5000010]; inline void add(int x,int y,int val){ data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val; data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].val=0; } inline void bfs1(int sx,int sy){ queue<pa>q;memset(dis,-1,sizeof(dis)); q.push(make_pair(sx,sy));dis[sx][sy]=0; while(!q.empty()){ int x=q.front().first,y=q.front().second;q.pop(); for(int k=0;k<4;++k){ int xx=x+dx[k],yy=y+dy[k]; if(xx<1||xx>n||yy<1||yy>m||mp[xx][yy]!='.') continue; if(dis[xx][yy]!=-1) continue;dis[xx][yy]=dis[x][y]+1; a[D][id[xx][yy]]=dis[xx][yy];q.push(make_pair(xx,yy)); } } } inline bool bfs(){ queue<int>q;memset(lev,0,sizeof(lev)); q.push(0);lev[0]=1; while(!q.empty()){ int x=q.front();q.pop(); for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(lev[y]||!data[i].val) continue; lev[y]=lev[x]+1;q.push(y);if(y==T) return 1; } }return 0; } int dinic(int x,int low){ if(x==T) return low;int tmp=low; for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(!data[i].val||lev[y]!=lev[x]+1) continue; int res=dinic(y,min(low,data[i].val)); tmp-=res;data[i].val-=res;data[i^1].val+=res; if(!res) lev[y]=0; if(!tmp) return low; }return low-tmp; } inline bool jud(int mid){ num=1;memset(h,0,sizeof(h)); for(int i=1;i<=ans;++i) add(0,i,1); for(int i=1;i<=D;++i) for(int j=1;j<=mid;++j) add(door[i][j],T,1); for(int i=1;i<=D;++i) for(int j=1;j<=ans;++j) for(int k=a[i][j];k<=mid;++k) add(j,door[i][k],1); int res=0;while(bfs()) res+=dinic(0,inf); return res==ans; } int main(){ // freopen("a.in","r",stdin); n=read();m=read();memset(a,inf,sizeof(a)); for(int i=1;i<=n;++i){ scanf("%s",mp[i]+1); for(int j=1;j<=m;++j) if(mp[i][j]=='.') id[i][j]=++tot; }ans=tot; for(int i=1;i<=n;++i) for(int j=1;j<=m;++j){ if(mp[i][j]!='D') continue;++D;bfs1(i,j); for(int k=1;k<=400;++k) door[D][k]=++tot; }T=tot+1; int l=0,r=400; while(l<=r){ int mid=l+r>>1; if(jud(mid)) r=mid-1; else l=mid+1; }if(r==400) puts("impossible"); else printf("%d\n",r+1); return 0; }
相关文章推荐
- 【枚举】【二分答案】【分块答案】【BFS】【最大流】【Dinic】bzoj1189 [HNOI2007]紧急疏散evacuate
- 【BZOJ1189】【HNOI2007】紧急疏散evacuate 二分答案+最大流check
- BZOJ 1189 HNOI2007 紧急疏散evacuate 二分答案+最大流
- [BZOJ1189][HNOI2007]紧急疏散evacuate(bfs+二分+最大流)
- BZOJ 1189 HNOI 2007 紧急疏散 evacuate 二分答案 最大流
- BZOJ 1189: [HNOI2007]紧急疏散evacuate( BFS + 二分答案 + 匈牙利 )
- bzoj1189: [HNOI2007]紧急疏散evacuate(二分+最大流+宽搜)
- 【BZOJ1189】[HNOI2007]紧急疏散evacuate【最大流】【二分】
- BZOJ 1189 [HNOI2007]紧急疏散evacuate 二分+最大流
- BZOJ1189【HNOI2007】紧急疏散evacuate <二分答案+网络流>
- BZOJ1189: [HNOI2007]紧急疏散evacuate 二分+最大流
- BZOJ 1189: [HNOI2007]紧急疏散evacuate|网络流|二分答案
- [省选前题目整理][BZOJ 1189][HNOI 2007]紧急疏散(BFS+二分+最大流)
- BZOJ 1189 紧急疏散evacuate 二分+BFS+最大流
- BZOJ 1189([HNOI2007]紧急疏散evacuate-网络流二分+拆点)
- 【BZOJ】1189: [HNOI2007]紧急疏散evacuate(二分+bfs+网络流)
- [BZOJ1189][HNOI2007]紧急疏散evacuate(二分+网络流)
- 【二分答案】【最大流】[HNOI2007]紧急疏散EVACUATE
- 【bzoj1189】[HNOI2007]紧急疏散evacuate 二分+dinic
- BZOJ1189 [HNOI2007]紧急疏散evacuate 【二分 + 网络流】