8102年,Normalgod在GLaDOS的幫助下,研製出了傳送槍。但GLaDOS想把傳送槍據爲己有,因而把Normalgod扔進了一間實驗室。這間實驗室是一棵有n個節點的樹。如今Normalgod在一號節點,出口也在一號節點,但爲了打開它,必須通過每個節點按下每一個節點的開關,出口才能打開。GLaDOS爲了殺死Normalgod,開始在實驗室裏釋放毒氣,所以Normalgod必須儘快逃出這間實驗室。 固然,Normalgod手中的傳送槍是可使用的。傳送槍能夠發射出兩個顏色不一樣的傳送門。Normalgod能夠從其中一個傳送到另外一個。儘管傳送槍能夠在視野範圍內的任何一個通過特殊處理的表面打開一扇傳送門,但這間實驗室的設計使得Normalgod只能在他所處的房間內打開一個傳送門。 在已經存在了一個同顏色的傳送門時,打開新的傳送門會使與它同顏色的舊門消失。傳送和打開傳送門所需時間爲0。 顯然,利用傳送槍會讓Normalgod更快解決謎題,可Normalgod死在了按下最後一個按鈕的路上。儘管如此,GLaDOS仍是很想知道到底Normalgod最快能用多久逃出去,這對她的實驗室設計方法論有重要的指導做用。做爲GLaDOS的算法模塊,你要完成這個任務。本題時限爲2000ms
第一行一個整數n。以後n-1行,每行三個整數ui,vi,ai ,表示有一條從ui 連向vi ,花費時間爲ai 的通道。php
一行一個數T,表示最小的脫逃時間。ios
5
1 2 2
2 3 3
2 4 5
1 5 1算法
13ide
1–> open1–> 5–> open2–> use(1)–> 2–> 3–> open2–> use(1)–> 2–> 4–> open2–> use(1)–> exitui
題意:給定n個結點的樹,每條邊權wi,能夠進行傳送門操做,求通過每一個結點並最終回到根節點的最短路徑長度。spa
設dp[i][0/1]
0表示在i點及i點兒子設傳送門所能獲得的最大總和
1 表示不在i點及i點兒子設傳送門所能獲得的最大總和設計
首先,對於dp[i][1]的狀況,必定存在i點的祖先中有傳送門,這樣才能使結果更優。因此對於他的每個兒子都能跳回到他的祖先。但實際上只有使一個兒子跳回祖先時,才能保證fa->i的邊通過兩次。
不然轉化爲dp[i][0]的狀況。則咱們要使選的兒子最優。
dp[i][1]=max(dp[vi][1]+wi);
其次,對於dp[i][0]的狀況,在每一個兒子中設立傳送門並不會影響到其餘兒子,由於總能從兒子回到i時再在i重設傳送門。因此咱們就取每一個兒子設與不設的最優值之和。
dp[i][0]=Σmax(dp[vi][0],dp[vi][1]+wi);code
#include<iostream> #include<cstdio> #define ll long long using namespace std; const ll maxn=1e6+77; long long n,f[maxn][2],d[maxn],list[maxn],cnt; struct E { ll to,next,v; }e[maxn*2]; void add(ll u,ll v,ll val) { e[++cnt].to=v; e[cnt].next=list[u]; list[u]=cnt; e[cnt].v=val; } void dfs(ll u,ll fa) { for(ll i=list[u]; i; i=e[i].next) { ll v=e[i].to; if(v==fa) continue; dfs(v,u); d[u]=max(d[u],d[v]+e[i].v); f[u][0]+=f[v][0]+e[i].v*2; f[u][1]+=min(f[v][0]+e[i].v-d[v],f[v][1]+e[i].v*2); } } int main() { freopen("portal.in","r",stdin),freopen("portal.out","w",stdout); scanf("%lld",&n); for(ll i=1,x,y,z; i<=n-1; i++) scanf("%lld%lld%lld",&x,&y,&z),add(x,y,z),add(y,x,z); dfs(1,0); printf("%lld",f[1][1]); }