ZROJ#398. 【18提升7】隨機遊走(指望dp 樹形dp)

題意

~~[題目連接]~~版權緣由就不發了。。c++

給出一棵樹,求出任意兩點之間指望距離的最大值spa

Sol

比較清真的一道題吧。。code

設$f[x]$表示從$x$走到$x$的父親的指望步數get

$g[x]$表示從父親走來的指望步數it

$d[x]$表示$x$節點的度數class

不可貴到方程$f[x] = \sum_{to \in son[x]} f[to] + d[x]$while

$g[x] = g[fa[x]] + \sum_{to \in son[fa[x]] \text{且} to \not = x} f[to] + d[fa[x]]$co

最後計算的時候維護向上向下最大值便可push

固然,仔細觀察不難發現$f[x]$即爲子樹中全部節點的度數return

$g[x]$爲整棵樹中除子樹外節點的度數

考慮每條邊的貢獻後不可貴到

$f[x] = 2 * siz[x] - 1$

$g[x] = 2 * (N - siz[x]) - 1$

#include<bits/stdc++.h>
#define chmax(a, b) (a = a > b ? a : b)
#define LL long long 
const int MAXN = 1e5 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
std::vector<int> v[MAXN];
int N, up[MAXN], down[MAXN], d[MAXN], siz[MAXN], ans, f[MAXN], g[MAXN];
void dfs3(int x, int fa) {
	siz[x] = 1;
	for(int i = 0, to; i < v[x].size(); i++) {
		if((to = v[x][i]) == fa) continue;
		dfs3(to, x);
		siz[x] += siz[to];
		
		ans = std::max(ans, std::max(up[x] + g[to] + down[to], down[x] + f[to] + up[to]));
		chmax(up[x], up[to] + f[to]);
		chmax(down[x], down[to] + g[to]);
	//	chmax(ans, up[x] + down[x]);
	}
	f[x] = (siz[x] << 1) - 1;
	g[x] = ((N - siz[x]) << 1) - 1;
}
int main() {
	N = read();
	for(int i = 1; i < N; i++) {
		int x = read(), y = read(); d[x]++; d[y]++;
		v[x].push_back(y); v[y].push_back(x); 
	}
	dfs3(1, 0);
	printf("%lld", ans); puts(".00000");
	return 0;
}
相關文章
相關標籤/搜索