【换根DP】STA-Station—洛谷P3478 [POI2008]

STA-Station—洛谷P3478 [POI2008]

思路

如果 u , v u, v u,v 两个点直接相连,我们可以直接通过其中一个点的 “以这个结点为根时,所有结点的深度之和” 来推出另一个点的 “以这个结点为根时,所有结点的深度之和” 。

如图:

C o d e Code Code

#include 
#define int long long
#define sz(a) ((int)a.size())
#define all(a) a.begin(), a.end()
using namespace std;
using PII = pair<int, int>;
using i128 = __int128;
const int N = 2e5 + 10;

int n;

void solve() {
	cin >> n;
	vector<vector<int>> g(n + 1);
	for (int i = 1; i <= n - 1; i ++) {
		int a, b;
		cin >> a >> b;
		g[a].push_back(b);
		g[b].push_back(a);
	}
	
	// root = 1时各个点的深度、每个点的子节点的数量(包括自身)
	vector<int> deep(n + 1, -1), num(n + 1, 0);
	auto dfs1 = [&] (auto dfs1, int u) ->int {
		int total = 1;
		for (auto v : g[u]) {
			if (deep[v] == -1) {
				deep[v] = deep[u] + 1;
				total += dfs1(dfs1, v);
			}
		}
		num[u] = total;
		return total;
	};
	deep[1] = 1;
	num[1] = n;
	dfs1(dfs1, 1);
	
	// 计算以每个点为根节点时的所有节点深度之和
	vector <int> sum(n + 1, 0);
	for (int i = 1; i <= n; i ++) {
		sum[1] += deep[i];
	}
	auto dfs2 = [&] (auto dfs2, int u) ->void {
		for (auto v : g[u]) {
			if (sum[v] == 0) {
				sum[v] = sum[u] + (n - num[v]) - num[v];
				dfs2(dfs2, v);
			}
		}
	};
	dfs2(dfs2, 1);
	
	int sum_max = -1, idx = -1;
	for (int i = 1; i <= n; i ++) {
		if (sum[i] > sum_max) {
			sum_max = sum[i];
			idx = i;
		}
	}
	
	cout << "         ";
	cout << idx << "\n";
}

signed main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int T = 1;
//	cin >> T; cin.get();
	while (T --) solve();
	return 0;
}

你可能感兴趣的:(DP,算法,c++)