世界中のコロンビアの火山旅行(木DP)

質問の意味:n個の国の合計、番号1〜nは、それぞれの側は、任意の2つの国二十から二までの間、過ごすには一定の時間を持っています。
火山の弟の合計がK国に行くことにしました。今、彼は知りたい:彼は、i番目の国からのものであれば、最短時間後にK国はどのくらいですか?

入力:
。3. 3(N、K)
。1 2 1
2 4 3
1
2
3
出力:
5
6。
5。

入力:
5 2
。1. 1. 3
2 3 2
4 3 3
。5. 1. 4
。5
。1
出力:
4
7。
5。
8。
4。

問題解決のアイデア:
サブツリーのルートノードの右側の合計はすべてのキーポイントと起点キーから2-最遠点を取るために開始点を構成します

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000010
typedef long long ll;
struct Edge{
	int to,w,nxt;
}edge[maxn];
int n,k,tot=0,vis[maxn],siz[maxn],head[maxn];
ll dis1[maxn],dis2[maxn],sum[maxn];
void add(int u,int v,int w){
	edge[++tot].to=v; edge[tot].w=w; edge[tot].nxt=head[u]; head[u]=tot;
	edge[++tot].to=u; edge[tot].w=w; edge[tot].nxt=head[v]; head[v]=tot;
}
void cmp(ll x,int u){
    if(x>=dis1[u]) dis2[u]=dis1[u],dis1[u]=x;
    else if(x>dis2[u]) dis2[u]=x;
}
void dfs1(int u,int fa){
	if(vis[u]) siz[u]=1;
	sum[u]=dis1[u]=dis2[u]=0;
    for(int i=head[u];~i;i=edge[i].nxt){
    	int to=edge[i].to,w=edge[i].w;
    	if(fa==to) continue;
    	dfs1(to,u);
    	siz[u]+=siz[to];
        sum[u]+=sum[to]+(siz[to]!=0)*2*w;
        cmp(dis1[to]+(siz[to]!=0)*w,u);
	}
}
void dfs2(int u,int fa){
	for(int i=head[u];~i;i=edge[i].nxt){
    	int to=edge[i].to,w=edge[i].w;
    	if(fa==to) continue;
    	sum[to]=sum[u]-2*w*(siz[to]!=0)+(n-siz[to]!=0)*2*w;
    	if(siz[to]!=n){
            if(dis1[to]+w==dis1[u]) cmp(dis2[u]+w,to);
            else cmp(dis1[u]+w,to);
        }
    	dfs2(to,u);
	}
}
int main(){
	memset(vis,0,sizeof(vis));
	memset(head,-1,sizeof(head));
	scanf("%d%d",&n,&k);
	for(int i=1;i<n;i++){
		int u,v,w; scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
	}
	for(int i=1;i<=k;i++){
		int x; scanf("%d",&x); 
		vis[x]=1;
	}
	dfs1(1,0); dfs2(1,0);
	for(int i=1;i<=n;i++) printf("%lld\n",sum[i]-dis1[i]);
	return 0;
}
公開された425元の記事 ウォン称賛15 ビュー10000 +

おすすめ

転載: blog.csdn.net/zt2650693774/article/details/104076955