题目描述
有一个村庄居住着 nn 个村民,有 n-1n−1 条路径使得这 nn 个村民的家联通,每条路径的长度都为 11。现在村长希望在某个村民家中召开一场会议,村长希望所有村民到会议地点的距离之和最小,那么村长应该要把会议地点设置在哪个村民的家中,并且这个距离总和最小是多少?若有多个节点都满足条件,则选择节点编号最小的那个点。
输入格式
第一行,一个数 nn,表示有 nn 个村民。
接下来 n-1n−1 行,每行两个数字 aa 和 bb,表示村民 aa 的家和村民 bb 的家之间存在一条路径。
输出格式
一行输出两个数字 xx 和 yy。
xx 表示村长将会在哪个村民家中举办会议。
yy 表示距离之和的最小值。
输入输出样例
输入 #1复制
4 1 2 2 3 3 4
输出 #1复制
2 4
说明/提示
数据范围
对于 70\%70% 数据 n \le 10^3n≤103。
对于 100\%100% 数据 n \le 5 \times 10^4n≤5×104。
找树的中心。
法一,用Floyd 时间复杂度O(n*n),代码略;
法二,dp;
#include<iostream>
#include<cstring>
using namespace std;
#define int long long
const int maxn=5e4+5;
const int INF=1e9+5;
int f[maxn],s[maxn],head[maxn<<1];
struct node{
int to,next;
}edge[maxn<<1];
int cnt=0;int ans=INF,now;
void add_edge(int from,int to)
{
cnt++;
edge[cnt].to=to;
edge[cnt].next=head[from];
head[from]=cnt;
}
void dfs1(int root,int fa,int dep)
{
s[root]=1;
for(int i=head[root];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(to!=fa)
{
dfs1(to,root,dep+1);
s[root]+=s[to];
}
}
f[1]+=dep;
}
void dfs2(int root,int fa)
{
for(int i=head[root];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(to!=fa)
{
f[to]=f[root]+s[1]-2*s[to];
dfs2(to,root);
}
}
ans=min(ans,f[root]);
}
signed main()
{
int n;cin>>n;
memset(head,-1,sizeof(head));
for(int i=1;i<n;i++)
{
int from,to;
cin>>from>>to;
add_edge(from,to);
add_edge(to,from);
}
dfs1(1,1,0);
dfs2(1,1);
for(int i=1;i<=n;i++)
{
if(f[i]==ans)
{
cout<<i<<" "<<ans<<endl;
return 0;
}
}
}
题目描述
设有一棵二叉树,如图:
其中,圈中的数字表示结点中居民的人口。圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为 11。如上图中,若医院建在1 处,则距离和 =4+12+2\times20+2\times40=136=4+12+2×20+2×40=136;若医院建在 33 处,则距离和 =4\times2+13+20+40=81=4×2+13+20+40=81。
输入格式
第一行一个整数 nn,表示树的结点数。
接下来的 nn 行每行描述了一个结点的状况,包含三个整数 w, u, vw,u,v,其中 ww 为居民人口数,uu 为左链接(为 00 表示无链接),vv 为右链接(为 00 表示无链接)。
输出格式
一个整数,表示最小距离和。
输入输出样例
输入 #1复制
5 13 2 3 4 0 0 12 4 5 20 0 0 40 0 0
输出 #1复制
81
说明/提示
数据规模与约定
对于 100\%100% 的数据,保证 1 \leq n \leq 1001≤n≤100,0 \leq u, v \leq n0≤u,v≤n,1 \leq w \leq 10^51≤w≤105。
树的中心题目同上;
#include<iostream>
#include<cstring>
using namespace std;
#define int long long
const int maxn=1e4+5;
const int INF=1e9+5;
int f[maxn],s[maxn],val[maxn];
int head[maxn];
struct node{
int to,next;
}edge[maxn];
int cnt=0;int ans=INF;
void add_edge(int from,int to)
{
cnt++;
edge[cnt].to=to;
edge[cnt].next=head[from];
head[from]=cnt;
}
void dfs1(int root,int fa,int dep)
{
s[root]=val[root];
for(int i=head[root];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(to!=fa)
{
dfs1(to,root,dep+1);
s[root]+=s[to];
}
}
f[1]+=val[root]*dep;
}
void dfs2(int root,int fa)
{
for(int i=head[root];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(to!=fa)
{
f[to]=f[root]+s[1]-2*s[to];
dfs2(to,root);
}
}
ans=min(ans,f[root]);
}
signed main()
{
int n;cin>>n;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
{
cin>>val[i];
int a1,a2;cin>>a1>>a2;
if(a1){
add_edge(i,a1);
add_edge(a1,i);
}
if(a2)
{
add_edge(i,a2);
add_edge(a2,i);
}
}
dfs1(1,0,0);
dfs2(1,0);
cout<<ans<<endl;
}