1. 程式人生 > >[bzoj1060] [ZJOI2007]時態同步

[bzoj1060] [ZJOI2007]時態同步

連接 由於 n-1 define 一個 long 相交 return oid

Description

  小Q在電子工藝實習課上學習焊接電路板。一塊電路板由若幹個元件組成,我們不妨稱之為節點,並將其用數字1,2,3….進行標號。電路板的各個節點由若幹不相交的導線相連接,且對於電路板的任何兩個節點,都存在且僅存在一條通路(通路指連接兩個元件的導線序列)。在電路板上存在一個特殊的元件稱為“激發器”。當激發器工作後,產生一個激勵電流,通過導線傳向每一個它所連接的節點。而中間節點接收到激勵電流後,得到信息,並將該激勵電流傳向與它連接並且尚未接收到激勵電流的節點。最終,激烈電流將到達一些“終止節點”——接收激勵電流之後不再轉發的節點。激勵電流在導線上的傳播是需要花費時間的,對於每條邊e,激勵電流通過它需要的時間為te,而節點接收到激勵電流後的轉發可以認為是在瞬間完成的。現在這塊電路板要求每一個“終止節點”同時得到激勵電路——即保持時態同步。由於當前的構造並不符合時態同步的要求,故需要通過改變連接線的構造。目前小Q有一個道具,使用一次該道具,可以使得激勵電流通過某條連接導線的時間增加一個單位。請問小Q最少使用多少次道具才可使得所有的“終止節點”時態同步?

Input

  第一行包含一個正整數N,表示電路板中節點的個數。第二行包含一個整數S,為該電路板的激發器的編號。接下來N-1行,每行三個整數a , b , t。表示該條導線連接節點a與節點b,且激勵電流通過這條導線需要t個單位時間

Output

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

Sample Input

3
1
1 2 1
1 3 3

Sample Output

2

Solution

考慮到要把每個點的時間調成最大的顯然最優,然後對於一條邊如果能影響到很多點且不超過上限,那麽改這條邊顯然比改下面的邊要優。

反正亂搞就行了。

#include<bits/stdc++.h>
using namespace std;

#define int long long  

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}

#define write(x) printf("%lld\n",x)

const int maxn = 6e5+10;

struct edge{int to,nxt,w;}e[maxn<<1];
int head[maxn],tot,ans,r,rt,dis[maxn],mx[maxn],n;

void ins(int u,int v,int w) {e[++tot]=(edge){v,head[u],w},head[u]=tot;}

void dfs(int x,int fa) {
    r=max(r,dis[x]);int bo=1; 
    for(int i=head[x];i;i=e[i].nxt) 
        if(e[i].to!=fa) bo=0,dis[e[i].to]=dis[x]+e[i].w,dfs(e[i].to,x),mx[x]=max(mx[x],mx[e[i].to]);
    if(bo) mx[x]=dis[x];
}

void calc(int x,int fa,int w) {
    for(int i=head[x];i;i=e[i].nxt) 
        if(e[i].to!=fa) calc(e[i].to,x,r-mx[e[i].to]),ans+=r-mx[e[i].to]-w;
}

signed main() {
    read(n);read(rt);
    for(int i=1,x,y,z;i<n;i++) read(x),read(y),read(z),ins(x,y,z),ins(y,x,z);
    dfs(rt,0);calc(rt,0,0);write(ans);
    return 0;
}

[bzoj1060] [ZJOI2007]時態同步