【GZOI 1032G】腐败分子看直播(树)
题目描述
随着里约奥运的开幕,在广州二高集训的腐败分子们悄悄有乐子了,他们常常围聚在某个人的电脑旁看奥运直播。但是,腐败分子的堕落性质决定了他们都不怎么想移动自己的位置,于是在谁的电脑上看直播成了腐败分子争吵的问题。
当然,腐败分子都是极其聪明的,他们马上把问题抽象为一个二叉树结构(如下图,其中圈中的数字表示腐败分子移动的艰难值,圈边上数字表示腐败分子的结点编号),他们把这个问题转换成在树上找一个点,使得所有人的移动艰难值最小。就下图而言,若在1处看直播,则各腐败分子的移动艰难值和=4+12+2*20+2*40=136;若在3处看直播,则移动艰难值和=4*2+13+20+40=81。(注意,相邻结点之间的距离为1。)显然,在3处看直播大家会更高兴。
现在,腐败分子们想知道他们最小的移动艰难值之和是多少,但是腐败分子的堕落性质决定了他们会把这个问题交给你解决,如果你解决不出来,他们就向Teacher Chen举报你腐败。
当然,腐败分子都是极其聪明的,他们马上把问题抽象为一个二叉树结构(如下图,其中圈中的数字表示腐败分子移动的艰难值,圈边上数字表示腐败分子的结点编号),他们把这个问题转换成在树上找一个点,使得所有人的移动艰难值最小。就下图而言,若在1处看直播,则各腐败分子的移动艰难值和=4+12+2*20+2*40=136;若在3处看直播,则移动艰难值和=4*2+13+20+40=81。(注意,相邻结点之间的距离为1。)显然,在3处看直播大家会更高兴。
现在,腐败分子们想知道他们最小的移动艰难值之和是多少,但是腐败分子的堕落性质决定了他们会把这个问题交给你解决,如果你解决不出来,他们就向Teacher Chen举报你腐败。
输入
输入第一行一个整数n,表示树的结点数(n<=100)。
接下来的n行每行描述了一个结点的状况,包含三个整数,整数之间用空格(一个或多个)分隔,其中:第一个数表示移动艰难值;第二个数为左链接,为0表示无链接;第三个数为右链接,为0表示无链接。
接下来的n行每行描述了一个结点的状况,包含三个整数,整数之间用空格(一个或多个)分隔,其中:第一个数表示移动艰难值;第二个数为左链接,为0表示无链接;第三个数为右链接,为0表示无链接。
输出
输出一个整数,表示最小的移动艰难值之和。
把树看成无根树,每一个点轮流做树根,求出每个点x深度的和的最小值便可。
1 #include <cstdio> 2 #include <vector> 3 4 int n,w[101],l,r,cost,ans(0x7fffffff); 5 std::vector<int> t[101]; 6 #define min(x,y) (x<y?x:y) 7 8 void dfs(int x,int fa,int dep){ 9 cost+=w[x]*dep; 10 for(int i=0;i<t[x].size();++i){ 11 int v=t[x][i]; 12 if((v==fa)||(v==0))continue; 13 dfs(v,x,dep+1); 14 } 15 } 16 17 int main(void){ 18 scanf("%d",&n); 19 for(int i=1;i<=n;++i){ 20 scanf("%d%d%d",&w[i],&l,&r); 21 t[i].push_back(l); 22 t[i].push_back(r); 23 t[l].push_back(i); 24 t[r].push_back(i); 25 } 26 for(int i=1;i<=n;++i){ 27 cost=0; 28 dfs(i,0,0); 29 ans=min(ans,cost); 30 } 31 printf("%d",ans); 32 }