• [BZOJ1189][HNOI2007]紧急疏散evacuate


    BZOJ
    Luogu
    以后不放题面了自己看去

    sol

    显然时间是二分的对吧。
    我们二分一个时间,假设为(mid),那么就要把每扇门拆成(mid)个点,各自向汇点连容量为1的边,表示每一扇门在一个单位时间里可以让一个人逃出。
    (BFS)预处理出每个人到每扇门的距离,然后如果这个人在(mid)时间内可以到达这扇门就向这扇门对应的时间点连一条容量为1的边。
    源点向每个人连容量为1的边,然后二分判断最大流是否等于总人数。
    但是!
    如果同一时间有多个人到达了同一扇门,然后其中一个人发挥谦让精神让另一个人先走了,自己在门这里等了一个单位时间才走的,那我们怎么处理呢?
    很简单。从每扇门对应时间(t)的点向(t+1)的点连一条(inf)的边,就可以解决这种问题了。

    code

    细节。。。还好吧
    一些需要注意的点在代码中已经用注释标出

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N = 40;
    const int inf = 1e9;
    int n,m,P[N][N],dis[N<<2][N][N],door,people;
    char g[N][N];
    struct node{int x,y;};
    int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
    queue<int>Q;
    queue<node>QQ;
    void BFS(int k,int p,int q)//第k扇门,它的位置是(p,q)
    {
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++)
    			dis[k][i][j]=inf;
    	dis[k][p][q]=0;QQ.push((node){p,q});
    	while (!QQ.empty())
    	{
    		int x=QQ.front().x,y=QQ.front().y;QQ.pop();
    		for (int d=0;d<4;d++)
    		{
    			int i=x+dx[d],j=y+dy[d];
    			if (i<1||i>n||j<1||j>m||g[i][j]!='.') continue;//这里如果写成" g[i][j]=='X' "的话在BZOJ上会WA(但是洛谷可以AC)
    			if (dis[k][i][j]>dis[k][x][y]+1)
    				dis[k][i][j]=dis[k][x][y]+1,QQ.push((node){i,j});
    		}
    	}
    }
    struct edge{int to,next,w;}a[N*N*N*N];
    int S,T,head[N*N*N],cnt,dep[N*N*N],cur[N*N*N];
    void link(int u,int v,int w)
    {
        a[++cnt]=(edge){v,head[u],w};
        head[u]=cnt;
        a[++cnt]=(edge){u,head[v],0};
        head[v]=cnt;
    }
    bool bfs()
    {
        memset(dep,0,sizeof(dep));
        dep[S]=1;Q.push(S);
        while (!Q.empty())
        {
            int u=Q.front();Q.pop();
            for (int e=head[u];e;e=a[e].next)
                if (a[e].w&&!dep[a[e].to])
                    dep[a[e].to]=dep[u]+1,Q.push(a[e].to);
        }
        return dep[T];
    }
    int dfs(int u,int flow)
    {
        if (u==T)
            return flow;
        for (int &e=cur[u];e;e=a[e].next)
            if (a[e].w&&dep[a[e].to]==dep[u]+1)
            {
                int temp=dfs(a[e].to,min(flow,a[e].w));
                if (temp) {a[e].w-=temp;a[e^1].w+=temp;return temp;}
            }
        return 0;
    }
    int Dinic()
    {
        int res=0;
        while (bfs())
        {
            for (int i=T;i;i--) cur[i]=head[i];
            while (int temp=dfs(S,inf)) res+=temp;
        }
        return res;
    }
    int check(int mid)
    {
    	S=door*mid+people+1;T=S+1;
    	memset(head,0,sizeof(head));cnt=1;
    	for (int k=1;k<=door;k++)
    		for (int t=1;t<=mid;t++)
    		{
    			link((k-1)*mid+t,T,1);
    			if (t<mid) link((k-1)*mid+t,(k-1)*mid+t+1,inf);
    		}
    	for (int i=1;i<=people;i++)
    		link(S,door*mid+i,1);
    	for (int k=1;k<=door;k++)
    		for (int i=1;i<=n;i++)
    			for (int j=1;j<=m;j++)
    				if (g[i][j]=='.'&&dis[k][i][j]<=mid)//这里一定要写" g[i][j]=='.' ",不然就会把自己这扇门的那个位置也算进去(就这样洛谷上还跑90分?)
    					link(door*mid+P[i][j],(k-1)*mid+dis[k][i][j],1);
    	return Dinic();
    }
    int main()
    {
    	scanf("%d %d",&n,&m);
    	for (int i=1;i<=n;i++)
    		scanf("%s",g[i]+1);
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++)
    			if (g[i][j]=='D')
    				BFS(++door,i,j);
    			else if (g[i][j]=='.')
    				P[i][j]=++people;
    	int l=0,r=people+1;
    	while (l<r)
    	{
    		int mid=l+r>>1;
    		if (check(mid)==people) r=mid;
    		else l=mid+1;
    	}
    	if (l==people+1) puts("impossible");
    	else printf("%d
    ",l);
    	return 0;
    }
    
  • 相关阅读:
    把影响集中到一个点
    How to avoid Over-fitting using Regularization?
    适定性问题
    Numerical Differentiation 数值微分
    What Every Computer Scientist Should Know About Floating-Point Arithmetic
    Generally a good method to avoid this is to randomly shuffle the data prior to each epoch of training.
    What is the difference between iterations and epochs in Convolution neural networks?
    Every norm is a convex function
    Moore-Penrose Matrix Inverse 摩尔-彭若斯广义逆 埃尔米特矩阵 Hermitian matrix
    perl 类里的函数调用其他类的函数
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8194711.html
Copyright © 2020-2023  润新知