1. 程式人生 > >BZOJ2435: [Noi2011]道路修建

BZOJ2435: [Noi2011]道路修建

ast noi2011 urn i++ ont != space bzoj2435 ret

【傳送門:BZOJ2435】


簡要題意:

  給出n個點,n-1條邊,顯然是一棵樹,每條邊有權值,而建設每條邊的代價是這條邊的權值乘上這條邊左邊的點數減去右邊的點數的絕對值

  求出總代價


題解:

  很水

  我們默認點1為樹的根,DFS將每個點遍歷一遍,求出每個點的深度和子樹點數

  然後遍歷一遍所有的邊,ans+=邊權*abs(n-深度更深的點的子樹點數*2)

  為什麽是n-深度更深的點的子樹點數*2,很簡單,這條邊右邊的點數=深度更深的點的子樹點數,那自然右邊的點數就等於剩下的點數咯,就=n-深度更深的點的子樹點數


參考代碼:

#include<cstdio>
#include
<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; struct node { int x,y,d,next; }a[2100000];int len,last[1100000]; int tot[1100000],dep[1100000]; void ins(int x,int y,int d) { len++; a[len].x=x;a[len].y=y;a[len].d=d; a[len].next
=last[x];last[x]=len; } void dfs(int x,int fa) { tot[x]=1;dep[x]=dep[fa]+1; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=fa) { dfs(y,x); tot[x]+=tot[y]; } } } int main() { int n; scanf("%d",&n); len
=0;memset(last,0,sizeof(last)); for(int i=1;i<n;i++) { int x,y,d; scanf("%d%d%d",&x,&y,&d); ins(x,y,d);ins(y,x,d); } dfs(1,0); LL ans=0; for(int i=1;i<=len;i+=2) { int x=a[i].x,y=a[i].y; if(dep[x]>dep[y]) swap(x,y); ans+=LL(a[i].d)*abs(n-tot[y]-tot[y]); } printf("%lld\n",ans); return 0; }

BZOJ2435: [Noi2011]道路修建