一.题目
Description
给出N个点,及你的出发点K.
接下来N-1行描述有关边的开始点,结束点,边长.保证图中不会有环
接下来给出数字J,代表你要走多少个点.
接下来J个数字,代表你要走过的点的编号.当然你可以自己选择行进的路线
不一定按给定编号顺序前行,求走过的最短距离。
Format
Input
第一行给出N,K。
2 <= N<= 50000,1<=K<=N
接下来N-1行,每行三个数,进来描述这个地图中的边,边长距离<=1000
接下来给出一个数字J,1<=J <= N-1代表你希望走过的J个点。
最后一行给出J个数字,代表点的编号。1<=编号<=N,且不等于K
Output
如题
Samples
输入数据 1
4 2
1 2 1
4 2 2
2 3 3
2
1 3
输出数据 1
5
输入数据 2
6 1
1 5 10
5 6 20
1 2 5
2 3 7
3 4 1
3
5 2 3
输出数据 2
32
二,思路
emmm...这题太简单了,直接看注释吧
三,代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
/*
pre[j]:对于第i条边来说,它的上一条边是哪一条边
now[x]:对于点x来说,最后一条描述它充当父结点的边是哪一条边
son[i]:在第i条边中,充当子结点的点是哪一个
*/
int eg,pre[100001],now[100001],ans,son[100001],vis[100001],bq[100001],n,k,s,dep[100001];
void dfs(int u,int fa,int d)
{
dep[u] = d;//记录u的深度
for(int i = now[u];i;i = pre[i])//遍历u的子节点
{
int v = son[i];
if(v == fa) continue;
dfs(v,u,d + bq[i]);
if(vis[v] == 1)//如果u的某一个子节点一定要被走过
{
s += 2 * bq[i];//s加上2倍的边权
vis[u] = 1;//那么u的父节点也一定会被走过
}
}
}
void adeg(int u,int v,int w)
{
pre[++eg] = now[u];
now[u] = eg;
son[eg] = v;
bq[eg] = w;
}
signed main()
{
cin>>n>>k;
for(int i = 1;i < n;i++)
{
int u,v,w;
cin>>u>>v>>w;
adeg(u,v,w);//邻接表的无向图建边
adeg(v,u,w);
}
int q,x;
cin>>q;
for(int i = 1;i <= q;i++)
{
cin>>x;
vis[x] = 1;
}
dfs(k,0,0);//从k开始dfs整棵树
for(int i = 1;i <= n;i++)
if(vis[i])
ans = max(ans,dep[i]);//ans为最深节点的深度
cout<<s - ans;
return 0;
}