zoukankan      html  css  js  c++  java
  • 洛谷 2691逃离

    传送门:

    https://www.luogu.org/problem/show?pid=2691

    题目描述

    一个n×n栅格是由n行和n列顶点组成的一个无向图,如图所示。用(i,j)表示处于第i行第j列的顶点。除了边界顶点(即满足i=1,i=n,j=1或j=n的顶点(i,j)),栅格中的所有其他顶点都有四个相邻的顶点。

    给定栅格中的m≤n2个起始点(x1,y1),…, (xm,ym),逃脱问题即确定从起始顶点到边界上的任何m个相异的顶点之间,是否存在m条顶点不相交的路径。例如,图中左边的栅格包含了一个逃脱,黑点表示起始点,一个逃脱路径由灰线表示;而右边的栅格则没有逃脱。

    现给定一个栅格的n和m,以及其中m个起始点的坐标,你只需要判断是否存在逃脱即可。

    输入输出格式

    输入格式:

    输入文件为escape.in

    第一行是一个整数,为n (n≤35)。

    第二行还是一个整数,为m。

    以下m行,第(i+2)行包含两个整数xi和yi,表示第i行第j列的点是起始点。输入数据保证不会出现起始点坐标相同的情况。

    输出格式:

    输出文件为escape.out

    只包括一行。若存在逃脱输出’YES’,不存在逃脱输出’NO’。

    输入输出样例

    输入样例#1:
    6
    10
    2 2
    2 4
    2 6
    3 1
    3 2
    3 4
    3 6
    4 2
    4 4
    4 6
    
    输出样例#1:
    YES

    裸的最大流

    每个点拆成两个点

    流量设置成1

    表示只能跑一遍

    然后边界向汇点连边跑dinic

    最终流量如果大于等于m就是逃离

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    using namespace std;
    #define inf 1<<30
    #define maxn 2333
    int n,m,k,head[maxn*maxn],lev[maxn*maxn],cur[maxn*maxn],tot=1,S,T,ans;
    queue<int>que; bool vis[maxn][maxn];
    
    struct Edge{
        int to,nxt,dis;
    }e[maxn*maxn];
    
    inline void add(int u,int v,int d)
    {
        e[++tot].to=v; e[tot].nxt=head[u]; e[tot].dis=d; head[u]=tot;
        e[++tot].to=u; e[tot].nxt=head[v]; e[tot].dis=0; head[v]=tot;
    }
    
    inline void read(int &now)
    {
        char ch=getchar(); now=0;
        while(ch>'9'||ch<'0') ch=getchar();
        while(ch>='0'&&ch<='9') now=now*10+ch-'0',ch=getchar(); 
    }
    
    bool bfs()
    {
        while(!que.empty()) que.pop();
        for(int i=S;i<=T;i++) lev[i]=-1,cur[i]=head[i];
        lev[S]=0; que.push(S);
        while(!que.empty())
        {
            int u=que.front();que.pop();
            for(int i=head[u];i;i=e[i].nxt)
            {
                if(e[i].dis>0&&lev[e[i].to]==-1)
                {
                    lev[e[i].to]=lev[u]+1;
                    que.push(e[i].to);
                    if(e[i].to==T) return true;
                }
            }
        }
        return false;
    }
    
    int dinic(int u,int flow)
    {
        if(u==T) return flow;
        int res=0,delta;
        for(int &i=cur[u];i;i=e[i].nxt)
        {
            if(e[i].dis>0&&lev[e[i].to]==lev[u]+1)
            {
                delta=dinic(e[i].to,min(e[i].dis,flow-res));
                e[i].dis-=delta; e[i^1].dis+=delta;
                res+=delta; if(res==flow) break;
            }
        }
        if(res!=flow) lev[u]=-1;
        return res;
        
    }
    
    int main()
    {
        read(n);
        read(m);
        S=0; T=2*n*n+1,tot=0;
        for(int i=1;i<=n*n;i++) add(i,i+n*n,1);
        for(int i=1;i<=m;i++)
        {
            int x,y; read(x); read(y);
            add(S,n*(x-1)+y,1);
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<n;j++)
            {
                add(n*n+n*(i-1)+j,n*(i-1)+j+1,1);
                add(n*n+n*(i-1)+j+1,n*(i-1)+j,1);
            }
        for(int i=1;i<n;i++)
            for(int j=1;j<=n;j++)
            {
                add(n*n+n*(i-1)+j,n*i+j,1);
                add(n*n+n*i+j,n*(i-1)+j,1);
            }
        for(int i=1;i<=n;i++)
        {
            add(n*n+i,T,1);
            add(n*n+(n-1)*n+i,T,1);
        }
        for(int i=2;i<n;i++)
        {
            add(n*n+n*(i-1)+1,T,1);
            add(n*n+n*i,T,1);
        }
        while(bfs())
            ans+=dinic(S,inf);
        if(ans>=m) cout<<"YES";
        else cout<<"NO";
        return 0;
    }
    View Code
  • 相关阅读:
    C学习笔记-gcc
    C学习笔记-makefile
    C学习笔记-makefile
    C学习笔记-基础数据结构与算法
    上下左右居中 无固定高的div
    Touch事件 移动端touch触摸事件
    让更多浏览器支持html5元素的简单方法
    跨子域的iframe高度自适应
    10进制转16进制,16进制转10进制,随机出一个6位十六进制颜色值
    ajax原理和XmlHttpRequest对象
  • 原文地址:https://www.cnblogs.com/chen74123/p/7581632.html
Copyright © 2011-2022 走看看