[省选联考 2021 A 卷] 支配

如果了解过支配树是什么,其实这道题会相当简单。

明显建立支配树。

考虑连接 \((s,t)\) 带来的影响。

对于 \(t\) 而言,它的最近支配点会变为 \(LCA(s,t)\)

考虑哪些点的受支配集会改变。显然是存在 \((u,v)\) 如果 \(u\) 的支配集被改变,那么 \(v\) 才可能会因为 \(u\) 而改变。

考虑如何改变。即,如果存在边 \((u,v)\),那么显然 \(u\)\(v\) 的最近支配点在一条链上。

如果 \(v\) 的最近支配点是 \(u\) 的新的最近支配点的祖先,那 \(v\) 必不可能被影响。否则 \(v\) 的最近支配点就会变得和 \(u\) 的一样。

不会快速建立支配树,但不影响总复杂度,扫一遍 \(O(n^2+nq)\)

#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define pii pair <int , int>
#define pll pair <LL , LL>
#define mp make_pair
#define fs first
#define sc second
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

//const int Mxdt=100000; 
//static char buf[Mxdt],*p1=buf,*p2=buf;
//#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,Mxdt,stdin),p1==p2)?EOF:*p1++;

template <typename T>
void read(T &x) {
	T f=1;x=0;char s=getchar();
	while(s<'0'||s>'9') {if(s=='-') f=-1;s=getchar();}
	while(s>='0'&&s<='9') {x=(x<<3)+(x<<1)+(s-'0');s=getchar();}
	x *= f;
}

template <typename T>
void write(T x , char s='\n') {
	if(!x) {putchar('0');putchar(s);return;}
	if(x<0) {putchar('-');x=-x;}
	T tmp[25]={},t=0;
	while(x) tmp[t++]=x%10,x/=10;
	while(t-->0) putchar(tmp[t]+'0');
	putchar(s); 
}

const int MAXN = 3e3 + 5;
int n , m , Q , head[MAXN] , to[MAXN * MAXN] , nxt[MAXN * MAXN] , cnt;
void add(int u , int v) {nxt[++cnt] = head[u];head[u] = cnt;to[cnt] = v;}
int deg[MAXN] , tmpd[MAXN] , f[MAXN][22] , dep[MAXN] , pre[MAXN];

int LCA(int x , int y) {
	if(dep[x] < dep[y]) swap(x , y);
	for (int i = 20; i >= 0; --i) {
		if(dep[f[x][i]] >= dep[y]) x = f[x][i];
		if(x == y) return x;
	} 
	for (int i = 20; i >= 0; --i) if(f[x][i] != f[y][i]) {
		x = f[x][i];
		y = f[y][i];
	}
	return f[x][0];
}

int ans;

int vis[MAXN];
void dfs(int x , int V) {
	vis[x] = 1;
	ans ++;
	for (int i = head[x]; i; i = nxt[i]) {
		int v = to[i];
		if(vis[v]) continue;
		if(dep[pre[v]] > dep[V]) dfs(v , V);
	}
}

void ddfs(int x) {
	vis[x] = 1;
	for (int i = head[x]; i; i = nxt[i]) {
		int v = to[i];
		if(vis[v]) continue;
		ddfs(v);
	}
}

vector <int> G[MAXN];

int main() {
	freopen("dominator.in" , "r" , stdin);
	freopen("dominator.out" , "w" , stdout);
	read(n),read(m),read(Q);
	for (int i = 1; i <= m; ++i) {
		int u , v;
		read(u),read(v);
		add(u , v);
	}
	
	for (int i = 2; i <= n; ++i) {
		G[1].push_back(i),deg[i] ++;
		vis[i] = 1;
		ddfs(1);
		for (int j = 1; j <= n; ++j) 
			if(!vis[j]) G[i].push_back(j),deg[j] ++;
			else vis[j] = 0;
	}
	
	queue <int> q;
	q.push(1);
	while(!q.empty()) {
		int x = q.front();
		q.pop();
		dep[x] = dep[pre[x]] + 1;
		f[x][0] = pre[x];
		for (int i = 1; i <= 20; ++i) f[x][i] = f[f[x][i - 1]][i - 1];
		for (int i = 0; i < (int)G[x].size(); ++i) {
			int v = G[x][i];
			deg[v] --;
			if(!deg[v]) q.push(v) , pre[v] = x;
		}
	}
	
	while(Q -- > 0) {
		int s , t;
		read(s),read(t);
		int v = LCA(s , t);
		ans = 0;
		if(dep[v] < dep[pre[t]]) dfs(t , v);
		write(ans);
		for (int i = 1; i <= n; ++i) vis[i] = 0;
	}
	
	return 0;
}
posted @ 2022-03-04 23:03  Reanap  阅读(46)  评论(0编辑  收藏  举报