Description
八中有N个教室,它们之间由N-1条边连接而成。 现在校长希望在某个教室召集同学们开会,那么这个地方应该比较方便才好, 也就是说所有同学到这个会议点,所走过的距离的总和应该越小越好。
Format
Input
第一行包含 1 个整数 n,表示教室数量(编号为1~n)。
接下来 n-1 行,每行包含 2 个用空格隔开的正整数 u、 v, 表示编号为 u 和编号为 v 的教室之间有一条路相连。
最后 1 行,包含 n 个正整数,每两个正整数之间用一个空格隔开, 其中第 i 个整数表示编号为 i 的教室的人口数量为
Wi 1 < n ≤ 200 ,000,0 < Wi ≤ 10 ,000
Output
第一行包含若干整数,表示可以建立会议点的教室编号(由小到大输出),每个数字后面有一个空格 第二行一个整数,表示所有人行程总和。
Samples
输入数据 1
5
1 2
1 3
3 4
3 5
13 4 12 20 40
输出数据 1
3
81
思路
直接在#C. 八中开会(进我个人主页自搜博客)的基础上将最后一步改成
for(int i = 1;i <= n;i++) mink += (deep[i] - 1) * p[i];
即可。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,h[1000001],p[1000001],vtx[1000001],nxt[1000001],ans[1000001],t,eg,a[1000001],v[1000001],minn = 999999999,mink,deep[1000001];
bool fl = 1;
void adeg(int u,int v)
{
eg++;
nxt[eg] = h[u];
h[u] = eg;
vtx[eg] = v;
}
void dfs_1(int u,int fa)
{
deep[u] = deep[fa] + 1;
for(int i = h[u]; i; i = nxt[i])
{
int v = vtx[i];
if(v == fa) continue;
dfs_1(v,u);
}
}
void dfs(int u,int fa)
{
//ans[u]:以u的直属子节点为根的子树中节点最多数量
//v[u]:以u为根的子树中有多少个节点
v[u] = 1;
ans[u] = 0;
for(int i = h[u];i;i = nxt[i])
{
int t = vtx[i];
if(t == fa) continue;
dfs(t,u);
v[u] += v[t];
ans[u] = max(ans[u],v[t]);
}
ans[u] = max(ans[u],n - v[u]);
}
signed main()
{
cin>>n;
for(int i = 1; i < n; i++)
{
int a,b;
cin>>a>>b;
adeg(a,b);
adeg(b,a);
}
for(int i = 1;i <= n;i++) cin>>p[i];
dfs(1,0);
for(int i = 1;i <= n;i++)
if(ans[i] < minn)
minn = ans[i],mink = i;
cout<<mink<<"\n";
dfs_1(mink,0);
mink = 0;
for(int i = 1;i <= n;i++) mink += (deep[i] - 1) * p[i];
cout<<mink;
return 0;
}