[省选联考 2021 A 卷] 支配

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

明显建立支配树。

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

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

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

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

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

不会快速建立支配树,但不影响总复杂度,扫一遍 O(n2+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 @   Reanap  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示