BZOJ 1189: [HNOI2007]紧急疏散evacuate|网络流|二分答案

来源:互联网 发布:知不足然后能自反也 编辑:程序博客网 时间:2024/04/30 05:02

S连“。”流量为1

二分答案 x

算出每一个门到每一个点的距离若小于x连边 流量为1

门连T 流量为 x

其实这个题完全不用拆点

因为门限制的流量为x   

若有x个点和门的dis<x  

每个点到门的距离肯定<=x

而且dis=x的点最多有一个

#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<queue>#include<vector>#include<set>#include<map>#include<iostream>#include<algorithm>#define T 99999using namespace std;int dx[]={0,0,-1,1};int dy[]={-1,1,0,0};int t[T];int head[444],nxt[T],lst[T],v[T];int id[33][33],mx[444],my[444];int dis[33][33],q[T][2],S,W,h[T];char s[33][33];int D[444];int n,m,tot=1,cnt,top,pl,sum;void insert(int x,int y,int z){//cout << x <<" "<< y <<" "<< z << endl;lst[++tot]=y; nxt[tot]=head[x]; head[x]=tot; v[tot]=z;lst[++tot]=x; nxt[tot]=head[y]; head[y]=tot; v[tot]=0;}void bfs(int xx,int yy,int f){memset(dis,0,sizeof(dis));int l=1,r=2; q[1][0]=xx,q[1][1]=yy;while(l<r){int x=q[l][0],y=q[l++][1];for(int i=0;i<4;i++){int nx=x+dx[i],ny=y+dy[i];if(s[nx][ny]=='.'){if(!dis[nx][ny]){dis[nx][ny]=dis[x][y]+1;if(dis[nx][ny]<=f){q[r][0]=nx,q[r++][1]=ny;    insert(id[nx][ny],id[xx][yy],1);}}}}}}bool BFS(){for(int i=1;i<=W;i++)D[i]=0;D[S]=1;int l=1,r=2;h[1]=S;while(l<r){int x=h[l++];for(int i=head[x];i;i=nxt[i])    if(v[i]>0&&!D[lst[i]])    {    D[lst[i]]=D[x]+1;    h[r++]=lst[i];    }    }    return D[W]!=0;}int dfs(int x,int f){int ww=0,w;if(x==W)return f;for(int i=head[x];i;i=nxt[i])    if(v[i]&&D[lst[i]]==D[x]+1)    {    w=dfs(lst[i],min(v[i],f-ww));    ww+=w;v[i]-=w,v[i^1]+=w;    if(f==ww)return ww;    }return ww;}bool jud(int x){memset(head,0,sizeof(head));tot=1;for(int i=1;i<=top;i++)bfs(mx[i],my[i],x);//system("pause");for(int i=1;i<=n;i++)    for(int j=1;j<=m;j++)    if(s[i][j]=='.')insert(S,id[i][j],1);for(int i=1;i<=top;i++)insert(id[mx[i]][my[i]],W,x);int ans=0;while(BFS())ans+=dfs(S,T);return ans==sum;}int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%s",s[i]+1);for(int i=1;i<=n;i++)    for(int j=1;j<=m;j++)        if(s[i][j]!='X')        {            id[i][j]=++cnt;            if(s[i][j]=='D')            {            mx[++top]=i;            my[top]=j;            }        }S=cnt+1,W=S+1;for(int i=1;i<=n;i++)    for(int j=1;j<=m;j++)        if(s[i][j]=='.')sum++;int l=0,r=sum,ans=0;while(l<=r){int mid=(l+r)>>1;if(jud(mid))ans=mid,r=mid-1;else l=mid+1;}if(!ans)printf("impossible");else cout << ans;}


0 0
原创粉丝点击