• [POI2008]STA-Station


    https://www.luogu.com.cn/problem/P3478
    一道换根DP题。设f[i]为以i为根的答案。先通过一遍dfs,求出f[1]的值。再自上而下进行DP,求出所有儿子节点的值。若节点u的父亲为fa,我们考虑根从fa变为u后,f[fa]怎样得到f[u]。
    再u下方的节点(siz[u])贡献会减去1,在u及其上方(n - siz[u])的贡献会加上1.那么f[u] = f[fa] + n - 2 * siz[u].

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    
    const int N = 1e6 + 100; 
    typedef long long LL;
    
    LL f[N], dn[N], siz[N];
    int head[N], cnt;
    int n;
    struct Edge {
    	int v, nxt;
    } e[N <<1];
    
    void dfs1(int u, int fa) {
    	siz[u] = 1;
    	for(int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].v;
    		if( v == fa)	continue;
    		dfs1(v, u);
    		dn[u] += dn[v] + siz[v];
    		siz[u] += siz[v];
    	} 
    }
    
    void dfs2(int u, int fa) {
    	if(u == 1)
    		f[u] = dn[u];
    	else f[u] = f[fa] + n - 2 * siz[u];
    	for(int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].v;
    		if( v == fa)	continue;
    		
    		dfs2(v, u); 
    	}
    } 
    
    void AddEdge(int u, int v, int w) {
    	e[++cnt].v = v;
    	e[cnt].nxt = head[u];
    	head[u] = cnt;
    }
    
    int main()
    {
    	scanf("%d", &n);
    	for(int i = 1; i < n; i ++) {
    		int u, v;
    		scanf("%d%d", &u, &v);
    		AddEdge(u, v, 1), AddEdge(v, u, 1);
    	}
    	dfs1(1, 0);
    	dfs2(1, 0);
    	LL ans = 0;
    	int id; 
    	for(int i = 1; i <= n; i ++) {
    		if( f[i] > ans) {
    			ans = f[i];
    			id = i;
    		}
    	}
    	
    	printf("%d
    ", id);
    	return 0;
    }
    
    
  • 相关阅读:
    Subsets II
    Pow(x, n)
    基本数据结构 —— 二叉搜索树(C++实现)
    基本数据结构 —— 堆以及堆排序(C++实现)
    Symmetric Tree
    Same Tree
    C++中三种传递参数方法的效率分析
    Word Search
    Subsets
    Combinations
  • 原文地址:https://www.cnblogs.com/wyy0804/p/13731778.html
Copyright © 2020-2023  润新知