洛谷 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; }