luogu P5180 【模板】支配树
https://www.luogu.com.cn/problem/P5180
这篇讲得好:https://www.luogu.com.cn/blog/Wankupi/solution-p5180
code:
#include<bits/stdc++.h>
#define N 400050
using namespace std;
vector<int> g[N], gr[N], gt[N];
int dfn[N], id[N], tot, Fa[N], semi[N], idom[N];
void dfs(int u) {
dfn[u] = ++ tot;
id[tot] = u;
for(int v : g[u]) {
if(dfn[v]) continue;
Fa[v] = u; dfs(v);
}
}
int fa[N], val[N];
int get(int x) {
if(fa[x] == x) return x;
int y = fa[x];
fa[x] = get(fa[x]);
if(dfn[semi[val[y]]] < dfn[semi[val[x]]]) val[x] = val[y];
return fa[x];
}
void merge(int x, int y) {
x = get(x), y = get(y);
fa[y] = x;
}
int dmin(int x, int y) {
return dfn[x] < dfn[y]? x : y;
}
int n, m, siz[N];
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++) fa[i] = i, siz[i] = 1;
for(int i = 1; i <= m; i ++) {
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v), gr[v].push_back(u);
}
dfs(1); dfn[0] = n + 1;
for(int i = n; i >= 1; i --) {
int u = id[i];
for(int v : gr[u]) { // get semi
if(dfn[v] < dfn[u]) semi[u] = dmin(semi[u], v);
else {
get(v);
semi[u] = dmin(semi[u], semi[val[v]]);
}
}
for(int v : gt[u]) {
get(v);
int x = val[v];
if(dfn[u] == dfn[semi[x]]) idom[v] = u;
else idom[v] = x;
}
val[u] = u;
merge(Fa[u], u);
gt[semi[u]].push_back(u);
}
for(int i = 2; i <= n; i ++) {
int u = id[i];
if(idom[u] != semi[u]) idom[u] = idom[idom[u]];
}
for(int i = n; i > 1; i --) {
int u = id[i];
siz[idom[u]] += siz[u];
}
for(int i = 1; i <= n; i ++) printf("%d ", siz[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2020-02-16 数学初联杂题乱讲