1. 程式人生 > >洛谷P1131 [ZJOI2007]時態同步

洛谷P1131 [ZJOI2007]時態同步

題目描述

Q在電子工藝實習課上學習焊接電路板。一塊電路板由若干個元件組成,我們不妨稱之為節點,並將其用數字1,2,3….進行標號。電路板的各個節點由若干不相交的導線相連線,且對於電路板的任何兩個節點,都存在且僅存在一條通路(通路指連線兩個元件的導線序列)。

在電路板上存在一個特殊的元件稱為“激發器”。當激發器工作後,產生一個激勵電流,通過導線傳向每一個它所連線的節點。而中間節點接收到激勵電流後,得到資訊,並將該激勵電流傳向與它連線並且尚未接收到激勵電流的節點。最終,激烈電流將到達一些“終止節點”――接收激勵電流之後不再轉發的節點。

激勵電流在導線上的傳播是需要花費時間的,對於每條邊e,激勵電流通過它需要的時間為te,而節點接收到激勵電流後的轉發可以認為是在瞬間完成的。現在這塊電路板要求每一個“終止節點”同時得到激勵電路――即保持時態同步。由於當前的構造並不符合時態同步的要求,故需要通過改變連線線的構造。目前小QQ有一個道具,使用一次該道具,可以使得激勵電流通過某條連線導線的時間增加一個單位。請問小Q最少使用多少次道具才可使得所有的“終止節點”時態同步?

輸入輸出格式

輸入格式:

 

第一行包含一個正整數N,表示電路板中節點的個數。

第二行包含一個整數S,為該電路板的激發器的編號。

接下來N1行,每行三個整數a,b,t。表示該條導線連線節點a與節點b,且激勵電流通過這條導線需要t個單位時間。

 

輸出格式:

 

僅包含一個整數V,為小Q最少使用的道具次數。

 

輸入輸出樣例

輸入樣例#1:  複製
3
1
1 2 1
1 3 3
輸出樣例#1:  複製
2

說明

對於40%的資料,N1000

對於100%的資料,N500000

對於所有的資料,te1000000

 

/*
    樹形DP水題一道。很容易看出來這是個樹!先求出點u一路走到黑的時間的最大值,轉移:dp[u] = max(dp[u],dp[v] + G[i].v)
    再用一次dfs求解答案 由於要使每個點到達時間相同,就要把不是最大時間的時間加到最大時間
    對於每一條邊來說 那麼就有ans += dp[u] - dp[v] - G[i].v
    記得dfs樹的時候不能dfs回去她的爸爸啊
*/

#include <bits/stdc++.h>

using namespace
std; const int maxn = 500005; int head[maxn],dp[maxn],cnt,n,s; long long ans; struct node{ int to,v,pre; }G[maxn*2]; void addedge(int from,int to,int v){ G[++cnt].to = to; G[cnt].v = v; G[cnt].pre = head[from]; head[from] = cnt; } void dfs1(int u,int fa){ for(int i = head[u];i;i = G[i].pre){ int v = G[i].to; if(v != fa){ dfs1(v,u); dp[u] = max(dp[u],dp[v] + G[i].v); } } } void dfs2(int u,int fa){ for(int i = head[u];i;i = G[i].pre){ int v = G[i].to; if(v != fa){ dfs2(v,u); ans += dp[u] - dp[v] - G[i].v; } } } int main(){ int a,b,t; scanf("%d%d",&n,&s); for(int i = 1;i <= n-1;i++){ scanf("%d%d%d",&a,&b,&t); addedge(a,b,t);addedge(b,a,t); } dfs1(s,0); dfs2(s,0); printf("%lld\n",ans); return 0; }