[Noip模擬題]寵物之戰senso

Description

衆所周知,moreD的寵物已經被moreD奴役得體無完膚。這隻寵物實在忍無可忍,把本身天天走魔法樹的經歷告訴了
本身的寵物。同時他還說明了本身爬樹是多麼地慢,以致於moreD天天都殘酷地訓練他爬樹。幸運的是moreD的寵物
的寵物不是moreD的寵物,moreD的寵物深知"寵物是用來寵的而不是用來奴役的"這一點,因此moreD的寵物對待自
己的寵物頗有愛。因此moreD的寵物與其寵物商量着要推翻moreD的暴政,方法是把moreD告上法庭,就以本身天天
被迫爬樹來作證據。因爲魔法樹是樹,訓練樹固然也是樹啦。moreD的訓練有着GX的文化,天天moreD會把本身的寵
物通靈到樹的一個端點上,這個通靈點可能與以前的通靈點相同。而後moreD命令他的寵物從這個點開始走,讓這
只寵物隨便訪問本身該天以前沒有訪問過的節點,一直走到該天無路可走,訓練纔會結束,寵物才能夠休息。more
D的寵物天天都會在這棵樹上訓練,幸運的是他天天走過的訓練路徑都不一樣,直到若干天后,全部可能的訓練路徑
都被走遍了。你,做爲moreD寵物的寵物,一隻被moreD的寵物寵着的寵物,固然想幫moreD的寵物算出他總共走過
的路徑長度啦。c++

Input

第一行包含兩個正整數N,M,表示樹的點數與邊數。接下來M行,每行三個正整數表示
Li,bi,ci分別表示樹上有一條長度爲Li的鏈接bi,ci兩個結點的邊。全部輸入的整數均不大於100,000,輸入的樹保
證連通,無重邊,無自環。git

Output

僅一行表示答案。spa

Solution:

本題讓咱們求樹上每個點到全部葉子節點的長度總和,那麼咱們能夠考慮每一條邊對答案的貢獻code

一條邊能夠把樹分紅兩個部分,而這條邊被通過的次數則能夠根據兩部分的size和葉子節點個數得出ip

咱們設sz[x]表明以x爲根的子樹的大小,num[x]表明以x爲根節點的子樹的葉子節點的個數ci

則一條邊的貢獻可表示爲:\(val*(sz[rt]-sz[v])*num[v]+val*(num[rt]-num[v])*sz[v]\)get

最後對每一條邊都統計答案就好了。input

注意本題輸入形式!!!it

Code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+1;
long long ans;
int rt,n,m,cnt,head[N],num[N],sz[N];
struct Edge{int nxt,to,val;}edge[N<<1];
void ins(int x,int y,int z){
    edge[++cnt].nxt=head[x];
    edge[cnt].to=y;edge[cnt].val=z;
    head[x]=cnt;
}
void dfs(int x,int fa){
    sz[x]=1;int flag=1;
    for(int i=head[x];i;i=edge[i].nxt){
        int y=edge[i].to;
        if(y==fa) continue;
        dfs(y,x);flag=0;
        sz[x]+=sz[y];num[x]+=num[y];
    }num[x]+=flag;
}
void calc(int x,int fa){
    for(int i=head[x];i;i=edge[i].nxt){
        int y=edge[i].to,z=edge[i].val;
        if(y==fa) continue;calc(y,x);
        int u1=num[1]-num[y],u2=sz[1]-sz[y];
        ans+=u1*1ll*sz[y]*z;ans+=z*1ll*u2*num[y];
    }
}
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
signed main(){
    n=read(),m=read();
    for(int i=1;i<=m;i++){
        int z=read(),x=read(),y=read();
        ins(x,y,z),ins(y,x,z);
    }dfs(1,0);calc(1,0);
    printf("%lld\n",ans);
    return 0;
}
相關文章
相關標籤/搜索