1. 程式人生 > >【樹形DP】 時態同步

【樹形DP】 時態同步

【描述】

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

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

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

【輸入】

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

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

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

【輸出】

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

【樣例輸入】[複製]

3
1
1 2 1
1 3 3

【樣例輸出】[複製]

2

提示

【資料規模】

對於40%的資料,N ≤ 1000

對於100%的資料,N ≤ 500000

對於所有的資料,te ≤ 1000000

 

本來是個SB題,但是dfs還要爆棧,坑死了。。改用bfs就能過了。。

【資料有問題,統計的過程中不開longlong,最後答案累加開longlong才能A掉...】

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5;
int Head[maxn],Next[maxn<<1],W[maxn<<1],V[maxn<<1],mx[maxn],cnt=0;
int N,root,a,b,t,MAX;
long long ANS=0;
int read(){
	int x=0;char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch))  x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return x;
}
void add(int u,int v,int w){
	++cnt;
	Next[cnt]=Head[u];
	V[cnt]=v,W[cnt]=w;
	Head[u]=cnt;
}
void bfs(){
	queue<int> Q;
	deque<int> ans;
	Q.push(root);
	mx[root]=1;
	while(!Q.empty()){
		int u=Q.front();
		Q.pop(),ans.push_front(u);
		for(int i=Head[u];i;i=Next[i]) if(!mx[V[i]])
		Q.push(V[i]),mx[V[i]]=1;
	}
	memset(mx,-1,sizeof(mx));
	while(!ans.empty()){
		int u=ans.front();
		ans.pop_front();
		MAX=0;
		for(int i=Head[u];i;i=Next[i])
			if(mx[V[i]]>=0)
				MAX=max(MAX,W[i]+mx[V[i]]);
		mx[u]=max(MAX,mx[u]);
		for(int i=Head[u];i;i=Next[i]) if(mx[V[i]]>=0)
		ANS+=mx[u]-mx[V[i]]-W[i];
	}
}
int main(){
	N=read(),root=read();
	for(int i=1;i<N;++i){
		a=read(),b=read(),t=read();
		add(a,b,t),add(b,a,t);
	}
	bfs();
	cout<<ANS<<'\n';
}