$[ NOI 2011 ] $道路修建
阿新 • • 發佈:2018-09-20
time 很多 inline script clu ++i getchar tdi 子圖
\(\\\)
\(Description\)
一棵\(N\)個節點的樹,每條邊有邊權,修建一條邊的代價是:
這條邊的邊權\(\times\)修建好的樹中,由該條邊分開的兩個子圖節點數之差的絕對值
求出修建整棵樹的代價。
- \(N\in [1,10^6]\)
\(\\\)
\(Solution\)
被原題題面"建造方案有很多種 "幹蒙...手玩樣例玩不出來...棄療看討論發現原來是說的這個意思...
一遍樹形\(DP\)就好了,統計子樹大小,分開的另一半的大小就是總點數\(-\)統計出的子樹大小,直接累加答案。
\(\\\)
\(Code\)
#include<cmath> #include<cstdio> #include<cctype> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define N 1000010 #define R register #define gc getchar using namespace std; typedef long long ll; inline int rd(){ int x=0; bool f=0; char c=gc(); while(!isdigit(c)){if(c=='-')f=1;c=gc();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();} return f?-x:x; } ll ans; int n,m,tot,sz[N],hd[N]; struct edge{int w,to,nxt;}e[N<<1]; inline void add(int u,int v,int w){ e[++tot].to=v; e[tot].w=w; e[tot].nxt=hd[u]; hd[u]=tot; } inline void dfs(int u,int fa){ sz[u]=1; for(R int i=hd[u],v;i;i=e[i].nxt) if((v=e[i].to)!=fa){ dfs(v,u); sz[u]+=sz[v]; ans+=(ll)e[i].w*(ll)abs(n-(sz[v]<<1)); } } int main(){ n=rd(); for(R int i=1,u,v,w;i<n;++i){ u=rd(); v=rd(); w=rd(); add(u,v,w); add(v,u,w); } dfs(1,0); printf("%lld\n",ans); return 0; }
$[\ NOI\ 2011\ ]\ $道路修建