继续看yan老哥的视频 还是一边看yan老哥视频一边敲代码 总感觉自己现在还不具备单独过提高组+题目的能力 写代码5分钟调试半小时 不是这错就是那错 ;这是个greedy题 而且要找出一个顺序 ;那么我们假设子节点b其父节点a
以及一个八杆子打不着的节点c ; 如果先选b,a 那么 cost为 a+2b+3c;
如果先选c 则为 c+2a+3b; 结果是看c 和 (a+b)/2的关系
那么推广到一般情况 结果就是看那一坨节点的平均值 ; 所以我们不停的找出非根节点的最大节点 ;然后将其并入父节点 ,最终根节点就是答案;
做法 ;
1 begin:f[i]=i; 最初各自为一组
2 接下来每次会将两组点合并,将其中一组点接在另一组点的后面
代码
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <map>
#include <set>
#include<iomanip>
#include <bits/stdc++.h>
/***************************************/
#define ll long long
#define int64 __int64
#define PI 3.1415927
#define INF 99999
#define MAXN 1000010
using namespace std;
struct node
{
int father, size ,sum;//父节点 子树个数 权值和
double avg;
}nodes[1010]; int n,root;
int find()//求当前这个点权值的非根节点
{
double avg=0; int ans=-1;
for(int i=1;i<=n;i++)
{
if(i!=root&&nodes[i].avg>avg)//根节点无法往上和并
{
avg=nodes[i].avg;
ans=i;
}
}
return ans;
}
int main()
{
cin>>n>>root; int res=0;
for(int i=1;i<=n;i++)
{ cin>>nodes[i].sum;
nodes[i].avg = nodes[i].sum;
nodes[i].size = 1;
res += nodes[i].sum;
}
int a,b;
for(int i=0;i<n-1;i++)
{
cin>>a>>b;
nodes[b].father=a ;
}
for(int i=0;i<n-1;i++)
{
int ver=find();
int father_baba =nodes[ver ].father;
res+= nodes[ver].sum*nodes[father_baba].size; //更新答案
nodes [ver].avg=-1;//已经被遍历
for(int j=1 ;j<=n;j++)//合并 删边 连结点
{
if(nodes[j].father== ver)
{
nodes[j].father =father_baba ;
}
}
nodes[father_baba].sum+=nodes[ver].sum;
nodes[father_baba].size+=nodes[ver].size;
nodes[father_baba].avg=(double)nodes[father_baba].sum/nodes[father_baba].size ;
} cout<<res<<endl;
return 0;
}