preparing

「NOIP 模拟赛 20230709」T3 - 与行星相会 题解

题目大意

原题

有一个 \(n\times n\) 的点阵,将相邻的点连边得到一个 \((n-1)\times(n-1)\) 的网格。\(q\) 次操作,每次删掉一条边,求删掉后边两端的点是否仍在一个连通块内。强制在线。

题解

显然,由于对偶图的性质,原图的一个割对应对偶图中的一个环,所以只需要删掉一条边时在对偶图中连边,若成环就输出 NO

#include<iostream>
#include<cstdio>
#define maxn 4500005
using namespace std;
int n,q,x,y,u,v,key,num,f[maxn];
int getfa(int p){if(f[p]==p) return p; return f[p]=getfa(f[p]);}
void uni(int p1,int p2){int r1=getfa(p1),r2=getfa(p2); if(r1==r2){printf("NO\n"); return;} printf("YES\n"); key++; f[r2]=r1;}
int main(){
	scanf("%d%d",&n,&q); num=(n-1)*(n-1)+1; for(int i=1;i<=num;i++) f[i]=i;
	while(q--){
		scanf("%d%d%d%d",&x,&y,&u,&v); x=(x+key)%n+1; y=(y+key)%n+1; u=(u+key)%n+1; v=(v+key)%n+1;
		if(x==u){
			if(x==1) uni(num,(x-1)*(n-1)+min(y,v));
			else if(x==n) uni(num,(x-2)*(n-1)+min(y,v));
			else uni((x-2)*(n-1)+min(y,v),(x-1)*(n-1)+min(y,v));
		}else{
			if(y==1) uni(num,(n-1)*(min(x,u)-1)+y);
			else if(y==n) uni(num,(n-1)*(min(x,u)-1)+y-1);
			else uni((n-1)*(min(x,u)-1)+y-1,(n-1)*(min(x,u)-1)+y);
		}
	} return 0;
}
posted @ 2023-07-09 15:55  qzhwlzy  阅读(17)  评论(0编辑  收藏  举报