题目大意:
镇海中学共有n个景点,每个景点均有若干学生正在参观。这n个景点以自然数1至n编号,每两个景点的编号均不同。每两个景点之间有且只有一条路径。选择哪个景点集中的学生,才能使所有学生走过的路径之和最小呢?
解题思路:
先以1为root搜一次,求出num[i]和ans[i],num[i]是从i到1的学生数量总和,ans[i]是从i到1的代价
然后再搜一次,每次加上(第一个景点的学生人数-上个景点的学生人数)×路径长度-这个景点的学生人数×路径长度,然后存于sum[i]中,sum[i]则为以i为集合点的代价 maxn为在最小代价的情况下的集合点源程序:
#include#include #define inf 1e18#define N 1000001using namespace std;struct node{ int x,y,w,next;}a[N];bool v[N];int n,len,maxn,xx[N],last[N];long long num[N],ans[N],sum[N];void add(int x,int y,int w){ a[++len].x=x;a[len].y=y;a[len].w=w;a[len].next=last[x];last[x]=len; a[++len].x=y;a[len].y=x;a[len].w=w;a[len].next=last[y];last[y]=len;}void dfs(int x,int rw){ v[x]=1;//已经搜过做标记 num[x]=xx[x]; ans[x]=xx[x]*rw;//计算num和ans for (int i=last[x];i;i=a[i].next) { int y=a[i].y; if (!v[y]) { dfs(y,rw+a[i].w);//往下搜 ans[x]+=ans[y];//加上搜到的结果 num[x]+=num[y];//加上搜到的结果 } }}int find(int x,int rw,int fa,int from){ v[x]=1; if (x!=1) sum[x]=sum[fa]+(num[1]-num[x])*a[from].w-num[x]*a[from].w;//计算代价 if (sum[x]