zoukankan      html  css  js  c++  java
  • ABC222F

    ABC222F - Expensive Expense

    解题思路

    这个题是一道经典的换根 DP。这道题硬算是 (O(n^2))。但是我们的时间限制要在 (O(n)) 以内。我们采用换根DP的技术。

    首先我们先算出每个子树内的答案,再考虑每个子树外对答案的贡献。子树内的比较简单,主要思维难度在子树外部的答案计算上。

    我们考虑现在计算根为 (u) 的子树。(u) 的父亲是 (fa),那么我们令状态为 (g_u),那么我们以 (fa) 为根时,维护出其每个子树的最大答案和次大的答案,然后扫一遍其原来树里的儿子。看起是不是最大答案,若是,那就用第二大的更新;否则用最大的更新。建议自己画图理解。我懒得画了

    林外值得注意的是,每个节点不能以自己为终点,所以要注意一下。具体看代码。

    最后注意一些细节,就可以了。

    代码

    //Don't act like a loser.
    //This code is written by huayucaiji
    //You can only use the code for studying or finding mistakes
    //Or,you'll be punished by Sakyamuni!!!
    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    
    int read() {
    	char ch=getchar();
    	int f=1,x=0;
    	while(ch<'0'||ch>'9') {
    		if(ch=='-')
    			f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9') {
    		x=x*10+ch-'0';
    		ch=getchar();
    	}
    	return f*x;
    }
    
    const int MAXN=2e5+10; 
    
    int n,cnt;
    int h[MAXN],f[MAXN],g[MAXN],fir[MAXN],sec[MAXN],mx[MAXN],c[MAXN];
    
    struct edge {
    	int to,w,nxt;
    }e[MAXN<<1];
    
    void addedge(int u,int v,int w) {
    	e[++cnt].to=v;
    	e[cnt].w=w;
    	e[cnt].nxt=h[u];
    	h[u]=cnt;
    }
    void insert(int u,int v,int w) {
    	addedge(u,v,w);
    	addedge(v,u,w);
    }
    
    void dfs(int u,int fa) {
    	mx[u]=c[u];
    	for(int i=h[u];i;i=e[i].nxt) {
    		int v=e[i].to;
    		
    		if(v!=fa) {
    			dfs(v,u);
    			mx[u]=max(mx[u],mx[v]+e[i].w);
    			f[u]=max(f[u],mx[v]+e[i].w);
    		}
    	}
    }
    void efs(int u,int fa) {
    	int a=0,b=0;
    	for(int i=h[u];i;i=e[i].nxt) {
    		int v=e[i].to;
    		
    		if(v!=fa) {
    			if(mx[v]+e[i].w>fir[u]) {
    				sec[u]=fir[u];
    				b=a;
    				a=v;
    				fir[u]=mx[v]+e[i].w; 
    			}
    			else if(mx[v]+e[i].w>sec[u]) {
    				b=v;
    				sec[u]=mx[v]+e[i].w; 
    			}
    		}
    	}
    	for(int i=h[u];i;i=e[i].nxt) {
    		int v=e[i].to;
    		if(v!=fa) {
    			g[v]=max((v==a? sec[u]:fir[u]),max(g[u],c[u]))+e[i].w;
    			efs(v,u);
    		}
    	}
    }
    
    signed main() {
    	//freopen(".in","r",stdin);
    	//freopen(".out","w",stdout);
    
    	cin>>n;
    	for(int i=1;i<n;i++) {
    		int u,v,w;
    		u=read(),v=read(),w=read();
    		insert(u,v,w);
    	}
    	for(int i=1;i<=n;i++) {
    		c[i]=read();
    	}
    	
    	dfs(1,0);
    	efs(1,0);
    	
    	for(int i=1;i<=n;i++) {
    		printf("%lld
    ",max(g[i],f[i]));
    	}
    
    
    	//fclose(stdin);
    	//fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    屏蔽/捕获并输出错误
    物理机转Hyper-V虚拟机
    Windows Server 2012无法安装 .NET3.5-安装角色或功能失败,找不到源文件
    IDRAC 固件升级操:
    网卡启动安装dell服务器OS
    服务器指定网卡进行备份数据避免影响业务口
    【转载】用户通过WEB方式更改AD域帐户密码
    Windows运维之Windows8.1-KB2999226-x64安装提示 此更新不适用你的计算机
    Exchange 退信550 5.1.11 RESOLVER.ADR.ExRecipNotFound
    优酷kux视频转MP4
  • 原文地址:https://www.cnblogs.com/huayucaiji/p/ABC222F.html
Copyright © 2011-2022 走看看