HDU 6604 Blow up the city DAG图上建支配树
Posted kaka0010
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6604 Blow up the city DAG图上建支配树相关的知识,希望对你有一定的参考价值。
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=6604
DAG图上的支配树
先来说一下支配树的简单概念,比如说我们要到a节点必须经过b节点,那么b节点就是a的支配点,在一棵支配树下,所有节点都是子树节点的支配点。
总所周知DAG图是有向无环图,因此处理起来会比一般图上的轻松很多。建树时我们通过拓扑序可以轻松遍历出所有点,然后我们逆着拓扑序看,如果这个点的所有出度的父节点都已经确定了,那么他的父节点就是他所有出度的点的公共祖先节点(不理解的可以动手画图),因为是逆拓扑序,因此这个点的所有出度肯定已经处理完毕了,可以保证做法的正确性。
题意
然后我们来看题意,给一个DAG图,然后询问每次给两个点,你可以堵掉一个点使得任意两个点中有一个无法到达出度为0的点,问有多少点可以堵。
分析
转化一下题意就变成了支配树上两个点之间经历了多少个点,这就是简单的度数问题了,我们求一个 d e p [ x ] + d e p [ y ] − d e p [ l c a ( x , y ) ] dep[x]+dep[y]-dep[lca(x,y)] dep[x]+dep[y]−dep[lca(x,y)]就可以了。
Code
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define re register
typedef long long ll;
typedef pair<ll, ll> PII;
typedef unsigned long long ull;
const int N = 1e5 + 10, M = 1e6 + 5, INF = 0x3f3f3f3f;
const int MOD = 1e9+7;
vector<int> G1[N], G2[N];
int in[N], n, m, q[N], idx;
int f[N][25], dep[N];
void tupo() {
idx = 0; queue<int> que;
for (int i = 1; i <= n; i++) {
if (!in[i]) que.push(i);
if (!G1[i].size()) G1[i].push_back(0), in[0]++;
}
while (que.size()) {
int now = que.front();
que.pop();
q[++idx] = now;
for (auto v : G1[now]) {
in[v]--;
if (!in[v]) que.push(v);
}
}
}
int lca(int x, int y) {
if (dep[x] > dep[y]) swap(x, y);
for (int i = 20; i >= 0; i--) if (dep[f[y][i]] >= dep[x]) y = f[y][i];
if (x == y) return x;
for (int i = 20; i >= 0; i--) {
if (f[y][i] != f[x][i])
y = f[y][i], x = f[x][i];
}
return f[x][0];
}
void solve() {
int T; cin >> T; while (T--) {
cin >> n >> m;
for (int i = 0; i <= n; i++) G1[i].clear(), G2[i].clear(), dep[i] = 0;
for (int i = 1; i <= m; i++) {
int u, v; cin >> u >> v;
G1[u].push_back(v);
in[v]++;
}
tupo();
for (int i = n; i >= 1; i--) {
int now = q[i];
if (!G1[now].size()) continue;
int _lca = G1[now][0];
for (int j = 1; j < G1[now].size(); j++) _lca = lca(_lca, G1[now][j]);
f[now][0] = _lca;
dep[now] = dep[_lca] + 1;
for (int j = 1; j <= 20; j++) f[now][j] = f[f[now][j-1]][j-1];
}
int qry; cin >> qry; while (qry--) {
int x, y; cin >> x >> y;
cout << dep[x] + dep[y] - dep[lca(x, y)] << endl;
}
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
return 0;
}
以上是关于HDU 6604 Blow up the city DAG图上建支配树的主要内容,如果未能解决你的问题,请参考以下文章
HDU 3371 Connect the Cities(prim算法)
hdu3371 Connect the Cities (MST)
hdu-3371 Connect the Cities---kruskal
hdu oj 3371 Connect the Cities (最小生成树)