bzoj 1189 二分+BFS+网络最大流
来源:互联网 发布:绿色建筑计算软件 编辑:程序博客网 时间:2024/06/05 16:52
~~~~~~~~~~~~~~~~~
题目大意:紧急疏散。有一张地图,‘.’表示人,‘D’表示门,人需要走曼哈顿距离的单位时间才1能到达门。一个门一个时刻只能通过一个人。求多长时间能疏散完毕。
首先第一感觉肯定要BFS,要算出每个人到每个门的用时
其次,优化题目意思,t时间,有num个人可以到达door[i],但是最多仅有t个人可以穿过这个门(每秒钟只可通过一个人),这就清晰的出现一个网络最大流的轮廓。
二分T时间(0-400),在T时间内,S向每个人建立流量为1的边,如果一个人在规定时间t内可以到达某一门,建立一条边,流量为1,最后门与汇点建立流量为T的边。二分跑出答案即可!
#include <map>#include <set>#include <queue>#include <stack>#include <math.h>#include <vector>#include <cstdio>#include <string>#include<string.h>#include <fstream>#include <iostream>#include <algorithm>using namespace std;#define exp 1e-8#define INF 100000000#define ll long long#define exp 1e-8#define INF 100000000#define ll long long#define set(a,b) memset(a,b,sizeof(a));#define for1(a,b) for(int a=1;a<=b;a++)//1---(b)#define for0(a,b) for(int a=0;a<=b;a++)//0---(b-1)#define For(i,a,b) for(int i=a;i<=b;i++)#define each(a,u) for(int a=head[u];a!=-1;a=e[a].next)void bug(string st="bug"){cout<<st<<endl;}template<typename __ll>inline void READ(__ll &m){ __ll 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();} m=x*f;}template<typename __ll>inline void read(__ll &m){READ(m);}template<typename __ll>inline void read(__ll &m,__ll &a){READ(m);READ(a);}template<typename __ll>inline void read(__ll &m,__ll &a,__ll &b){READ(m);READ(a);READ(b);}struct DOOR{ int x,y;}door[1000],CUR,tmp;int doorcnt=1;int cost[30][30][100];int dx[]={1,-1,0,0};int dy[]={0,0,1,-1};int g[30][30]; //墙是0 人是1 可移动的地方 们是2int n,m;#define INF 999999999;const int maxn=2000000; //边的数量,应该比正常边的数量多两倍const int MAXN=10000;//节点数int s,t,tot;int cur[MAXN];//当前弧优化int pre[MAXN];//先祖int level[MAXN];//高度int gap[MAXN];//gap优化struct EDGE{int to,cost,next;}edge[maxn];int head[maxn],cnt;inline void addedge(int a,int b,int c){edge[cnt].to=b;edge[cnt].cost=c;edge[cnt].next=head[a];head[a]=cnt++;edge[cnt].to=a;edge[cnt].cost=0;edge[cnt].next=head[b];head[b]=cnt++;}#define getid(i,j) (i-1)*n+jvoid build_graph(int n,int m,int mid) //节点数(1->n),边数{s=0,t=n*m+1,tot=n*m+2,cnt=0;//cnt=0为了更好的异或memset(head,-1,sizeof(head));for1(i,n) for1(j,m) if(g[i][j]==1) { addedge(s,getid(i,j),1); for1(idx,doorcnt-1) if(cost[i][j][idx]<=mid) addedge(getid(i,j),getid(door[idx].x,door[idx].y),1); } for1(idx,doorcnt-1) addedge(getid(door[idx].x,door[idx].y),t,mid);}int sap() //无需改动{memset(pre,-1,sizeof(pre));memset(gap,0,sizeof(gap));memset(level,0,sizeof(level)); gap[0]=tot;int u=s,ans=0,inf=INF;for(int i=0; i<tot; i++)//初始化当前弧为第一条弧cur[i]=head[i];while(level[s]<tot){bool flag=0;for(int &i=cur[u];i!=-1;i=edge[i].next) //读取边,并更新当前弧{int v=edge[i].to;if(edge[i].cost>0&&level[u]==level[v]+1){flag=1;if(edge[i].cost<inf)inf=edge[i].cost;pre[v]=u;u=v;if(u==t){while(u!=s) //结束后u==s{u=pre[u];edge[cur[u]].cost-=inf;edge[cur[u]^1].cost+=inf;//异或是找与其配对的边}ans+=inf;inf=INF;}break;}}if(!flag){if(--gap[level[u]]==0)//gap优化break;int minn=tot;for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(edge[i].cost>0&&level[v]<minn){minn=level[v];cur[u]=i;//更新当前弧,让其从度最小的线段开始}}level[u]=minn+1;gap[minn+1]++;if(u!=s)u=pre[u];}}return ans;}void bfs(int idx) //第几个门{ for1(i,n) for1(j,m) cost[i][j][idx]=INF; cost[door[idx].x][door[idx].y][idx]=0;//初始化 bool vis[30][30]; set(vis,0); CUR=door[idx]; queue<DOOR>que; que.push(CUR); vis[CUR.x][CUR.y]=1; while(!que.empty()) { CUR=que.front(); que.pop(); vis[CUR.x][CUR.y]=0; for0(i,4) { int x=CUR.x+dx[i]; int y=CUR.y+dy[i]; if(x>=1&&x<=n&&y>=1&&y<=m&&g[x][y]==1) { if(cost[x][y][idx]>cost[CUR.x][CUR.y][idx]+1) { cost[x][y][idx]=cost[CUR.x][CUR.y][idx]+1; if(!vis[x][y]) { vis[x][y]=1; tmp.x=x,tmp.y=y; que.push(tmp); } } } } }}int main(){ read(n,m); int sum=0,ans=-1; for1(i,n) { char ch[30]; scanf("%s",ch+1); for1(j,m) if(ch[j]=='X') g[i][j]=0; else if(ch[j]=='.') g[i][j]=1,sum++; else if(ch[j]=='D') { door[doorcnt].x=i,door[doorcnt++].y=j; g[i][j]=2; } } for1(i,doorcnt-1) bfs(i); //求最短距离 int l=0,r=410; while(l<r) { int mid=(l+r>>1); build_graph(n,m,mid); //新建图 if(sap()==sum) r=mid; //对比答案 else l=mid+1; } if(410==r) cout<<"impossible\n"; else cout<<r<<endl; return 0;}
0 0
- bzoj 1189 二分+BFS+网络最大流
- BZOJ 1189 紧急疏散evacuate 二分+BFS+最大流
- [省选前题目整理][BZOJ 1189][HNOI 2007]紧急疏散(BFS+二分+最大流)
- BZOJ-1189 紧急疏散evacuate BFS预处理+最大流+二分判定+神建模!!
- bzoj 1532(二分+最大流)
- bzoj 1305 二分+最大流
- BZOJ 1305 二分+网络流
- BZOJ 3130 二分+网络流
- BZOJ 1189 HNOI2007 紧急疏散evacuate 二分答案+最大流
- BZOJ 1189 [HNOI2007]紧急疏散evacuate 二分+最大流
- Codeforces 513F2 题解 (网络流-最大流 二分 BFS)
- hdu3468 最大流/二分匹配+BFS
- BZOJ 2095 [Poi2010]Bridges 二分+最大流
- bzoj 1532 二分答案+最大流判断
- BZOJ 1189: [HNOI2007]紧急疏散evacuate|网络流|二分答案
- POJ 3057 最大二分匹配+bfs + 二分
- BZOJ 1066: [SCOI2007]蜥蜴 网络最大流
- BZOJ 1458: 士兵占领 网络最大流
- java.lang.IllegalArgumentException: KeyValue size too large
- Linux防火墙iptables学习笔记(三)iptables命令详解和举例
- 获取应用是否允许通知
- org.springframework.beans.factory.BeanCreationException: Error creating bean with name
- Dalvik VM (DVM) 与Java VM (JVM)之间有哪些区别
- bzoj 1189 二分+BFS+网络最大流
- Zigbee入门
- Oracle存储过程学习记录
- 决策树--从原理到实现
- git学习
- 虚继承
- Linux防火墙iptables学习笔记(四)iptables实现NAT
- 设置环境变量 ---- bash和tcsh
- 汇编语言--前言