[省选联考 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;
}