[思维] P10572 [JRKSJ R8] +1-1

posted on 2024-06-09 04:17:25 | under | source

厉害题。首先膜拜考场过了的 myz,蒟蒻看了评讲才懂。

考虑怎么刷括号,注意到 ())( 这种没法刷,但是 (()) 就可以不断产生 \(2k\) 个新的括号。

考虑一条路径合法的条件,假如其一开始是 ()...() 一定合法。

否则,呈现为开头结尾皆为连续 (),但中间夹着一串不可名状之物 \(S\)。将 \(S\) 所有合法括号对删去后,必然呈现 )...)(...( 的形式,那么 \(S\) 的开头必须是 ((,结尾必须是 )),否则无法刷括号。注意到刷括号不能改变某种括号的奇偶性,所以要求最终剩下的左右括号个数的奇偶性相同。又因为删去的合法括号对中的括号总个数必然是偶数,所以得出一个判断条件:走过的路径长度为偶数,且 (( 先于 )) 出现。

这启示我们将 () 边单独拎出来,这构成二分图。

那么可以开始判定了:

  • 边界条件:若 \(c_x\ne\) (\(c_y\ne\) ),非法;若 \(x,y\) 在原图不连通,非法。

  • \(x,y\) 在二分图上连通,合法。否则需满足下列条件:

  • 刷括号条件:\(x\) 在二分图上的连通块存在 ( 与原图上 ( 相邻,且 \(y\) 在二分图连通块存在 ) 与原图上 ) 相邻即可。

  • 路径为偶数:\(x,y\) 所在连通块上存在奇环,就可以走奇环改变奇偶性得到偶数路径;若不存在奇环,那么构成二分图(注意和一开始只有 () 边的二分图区分),\(x\to y\) 的路径的奇偶性被唯一确定,若 \(x,y\) 在二分图不同侧才能有偶数路径。

代码

关于我把 col 开成 bool 类型于是调了好久的这件事。

#include<bits/stdc++.h>
#define NO {putchar('0'); continue;}
#define YES {putchar('1'); continue;}
using namespace std;

const int N = 5e5 + 5;
int n, m, q, u, v, fa[N], fa2[N], x, y;
bool col_left[N], col_right[N], flag_left[N], flag_right[N];
int col[N], jihuan[N];
char c[N];
vector<int> to[N];

inline int find(int fa[], int u) {return fa[u] == u ? u : fa[u] = find(fa, fa[u]);}
inline bool dfs(int u, int cl){
	bool fl = false; col[u] = cl;
	for(auto v : to[u])
		if(!col[v]) fl |= dfs(v, 3 - cl);
		else if(col[v] == col[u]) fl = true; 
	return fl;
}
int main(){
	scanf("%d%d%d %s", &n, &m, &q, c + 1);
	for(int i = 1; i <= n; ++i) fa[i] = fa2[i] = i;
	for(int i = 1; i <= m; ++i){
		scanf("%d%d", &u, &v), to[u].push_back(v), to[v].push_back(u);
		fa[find(fa, u)] = find(fa, v);
		if(c[u] != c[v]) fa2[find(fa2, u)] = find(fa2, v);
		if(c[u] == '(' && c[v] == '(') flag_left[u] = flag_left[v] = true;
		if(c[u] == ')' && c[v] == ')') flag_right[u] = flag_right[v] = true;
	}
	for(int i = 1; i <= n; ++i) col_left[find(fa2, i)] |= flag_left[i], col_right[find(fa2, i)] |= flag_right[i];
	for(int i = 1; i <= n; ++i) if(fa[i] == i) jihuan[i] = dfs(i, 1);
	
	while(q--){
		scanf("%d%d", &x, &y);
		if(find(fa, x) != find(fa, y) || c[x] != '(' || c[y] != ')') NO
		int fx = find(fa2, x), fy = find(fa2, y);
		if(fx == fy) YES
		if(col_left[fx] && col_right[fy] && (jihuan[find(fa, x)] || col[x] != col[y])) YES
		NO
	}
	return 0;
}
posted @ 2026-01-13 11:18  Zwi  阅读(0)  评论(0)    收藏  举报