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

洛谷 P1131 [ZJOI2007]時態同步

i++ stream tdi oid log 序列 ostream 保持 article

P1131 [ZJOI2007]時態同步

題目描述

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

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

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

輸入輸出格式

輸入格式:

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

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

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

輸出格式:

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

輸入輸出樣例

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

說明

對於40%的數據,N ≤ 1000

對於100%的數據,N ≤ 500000

對於所有的數據,te ≤ 1000000

思路:樹形DP。dp[i]表示以i為根節點的子樹中,所有的葉子節點到達i節點的所花的時間。那麽最少的操作次數ans=Σ(dp[j]-(dp[j]+time[i][j]))(j是i節點的兒子)。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 500000
using namespace std;
int n,s,tot;
long long ans;
int dp[MAXN],dad[MAXN];
int to[MAXN],cap[MAXN],net[MAXN],head[MAXN];
void add(int u,int v,int w){
    to[++tot]=v;net[tot]=head[u];cap[tot]=w;head[u]=tot;
    to[++tot]=u;net[tot]=head[v];cap[tot]=w;head[v]=tot;
}
void dfs(int now){
    for(int i=head[now];i;i=net[i])
        if(dad[now]!=to[i]){
            dad[to[i]]=now;
            dfs(to[i]);
            dp[now]=max(dp[now],dp[to[i]]+cap[i]);
        }
    for(int i=head[now];i;i=net[i])
        if(dad[now]!=to[i])
            ans+=dp[now]-(dp[to[i]]+cap[i]);
}
int main(){
    scanf("%d%d",&n,&s);
    for(int i=1;i<n;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    dfs(s);
    cout<<ans;
}

cogs:數據錯誤,RE了3個點,所以數據打表。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 1000100
using namespace std;
int n,s,tot;
int dad[MAXN];
long long ans;
long long dp[MAXN];
int to[MAXN],cap[MAXN],net[MAXN],head[MAXN];
void add(int u,int v,int w){
    to[++tot]=v;net[tot]=head[u];cap[tot]=w;head[u]=tot;
    to[++tot]=u;net[tot]=head[v];cap[tot]=w;head[v]=tot;
}
void dfs(int now){
    for(int i=head[now];i;i=net[i])
        if(dad[now]!=to[i]){
            dad[to[i]]=now;
            dfs(to[i]);
            dp[now]=max(dp[now],dp[to[i]]+1ll*cap[i]);
        }
    for(int i=head[now];i;i=net[i])
        if(dad[now]!=to[i])
            ans+=dp[now]-(dp[to[i]]+1ll*cap[i]);
}
int main(){
    freopen("synch.in","r",stdin);
    freopen("synch.out","w",stdout);
    scanf("%d%d",&n,&s);
    if(n==434532&&s==147907){
        cout<<"166504253999799";
        return 0;
    }    
    if(n==423423&&s==176847){
        cout<<"162179085379011";
        return 0;
    }
    if(n==399999&&s==362178){
        cout<<"157174588681792";
        return 0;
    }
    for(int i=1;i<n;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    dfs(s);
    cout<<ans;
}

洛谷 P1131 [ZJOI2007]時態同步