• bzoj3743: [Coci2015]Kamp


    首先树dp求出一个点的答案

    然后再一遍dfs换根(是叫做换根吗..

    详见代码

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #define ll long long
    #define N 500005
    #define M 1000006
    
    using namespace std;
    inline int read(){
    	int ret=0;char ch=getchar();
    	while (ch<'0'||ch>'9') ch=getchar();
    	while ('0'<=ch&&ch<='9'){
    		ret=ret*10-48+ch;
    		ch=getchar();
    	}
    	return ret;
    }
    
    struct edge{
    	int adj,next,len;
    	edge(){}
    	edge(int _adj,int _next,int _len):adj(_adj),next(_next),len(_len){}
    } e[M];
    int n,g[N],m;
    void AddEdge(int w,int u,int v){
    	e[++m]=edge(v,g[u],w);g[u]=m;
    	e[++m]=edge(u,g[v],w);g[v]=m;
    }
    
    ll f[N],h[N],t[N],t0[N];
    ll f0[N],h0[N];
    int size[N],l[N];
    int size0[N];
    bool vis[N];
    void dfs(int u){
    	vis[u]=1;
    	f[u]=l[u];h[u]=2*l[u];t[u]=0;t0[u]=0;
    	for (int i=g[u];i;i=e[i].next){
    		int v=e[i].adj;
    		if (vis[v]) continue;
    		l[v]=e[i].len;
    		dfs(v);
    		f[u]+=h[v];
    		h[u]+=h[v];
    		t0[u]=max(t0[u],h[v]-f[v]);
    		if (t0[u]>t[u]) swap(t0[u],t[u]);
    		size[u]+=size[v];
    	}
    	if (!size[u]) f[u]=h[u]=0;
    	else f[u]-=t[u];
    	vis[u]=0;
    }
    
    ll ans[N];
    void solve(int u){
    	vis[u]=1;
    	
    	f[u]=l[u];h[u]=2*l[u];t[u]=0;t0[u]=0;
    	for (int i=g[u];i;i=e[i].next){
    		int v=e[i].adj;
    		l[v]=e[i].len;
    		f[u]+=h[v];
    		h[u]+=h[v];
    		t0[u]=max(t0[u],h[v]-f[v]);
    		if (t0[u]>t[u]) swap(t0[u],t[u]);
    		size[u]+=size[v];
    	}
    	if (!size[u]) f[u]=h[u]=0;
    	else f[u]-=t[u];
    	
    	ans[u]=f[u];
    	f0[u]=f[u];h0[u]=h[u];
    	size0[u]=size[u];
    	for (int i=g[u];i;i=e[i].next){
    		int v=e[i].adj;
    		if (vis[v]) continue;
    		swap(l[u],l[v]);
    		if ((size[u]-=size[v])){
    			h[u]+=(ll)2*l[u]-h[v];
    			f[u]+=(ll)l[u]-h[v];
    			if (h[v]-f[v]==t[u]) f[u]+=t[u]-t0[u];
    		}
    		else f[u]=h[u]=0;
    		
    		solve(v);
    		
    		f[u]=f0[u];h[u]=h0[u];
    		size[u]=size0[u];
    		swap(l[u],l[v]);
    	}
    	vis[u]=0;
    }
    
    int main(){
    	n=read();int men=read();
    	for (int i=1;i<n;++i) AddEdge(read(),read(),read());
    	memset(size,0,sizeof(size));
    	while (men--) ++size[read()];
    	memset(vis,0,sizeof(vis));
    	l[1]=0;
    	dfs(1);
    	solve(1);
    	for (int i=1;i<=n;++i) printf("%lld
    ",ans[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    分治法求最大子序列
    6.2 链表 (UVa 11988, 12657)
    6.1 栈和队列 (UVa 210, 514, 442)
    S-Tree (UVa 712) 二叉树
    Equilibrium Mobile (UVa 12166) dfs二叉树
    Patrol Robot (UVa 1600) BFS
    Knight Moves (UVa 439) BFS
    Tree Recovery (UVa 536) 递归遍历二叉树
    Parentheses Balance (Uva 673) 栈
    Self-Assembly (UVa 1572)
  • 原文地址:https://www.cnblogs.com/wangyurzee7/p/5181817.html
Copyright © 2020-2023  润新知