HNUOJ 13309 Intrepid climber(搜索)

Intrepid climber
Time Limit: 2000ms, Special Time Limit:5000ms, Memory Limit:65536KB
Total submit users: 16, Accepted users: 15
Problem 13309 : No special judgement
Problem description

Who would guess? You climbed the highest mountain of your city. You are so excited about it that you need to tell it to all your friends, and you decided to start with those that are trying to be exactly where you are at this precise moment.

The mountain has N landmarks, and one of them is the top of the mountain, where you are now. Each of your friends that is climbing the mountain is in some other landmark, and you want to visit all of them. There are tracks that connect pairs of landmarks in such a way that there exists exactly one route (that is, a sequence of consecutive tracks) that goes down from the top of the mountain to each other landmark. To visit two friends in two different landmarks, you may have to go down some tracks, climb others, and go down others again. Going down the mountain is “easy”, so you do not consume energy when you go down through the tracks. But each time you climb a track, you consume a certain amount of energy. After visiting all your friends, you can just sit and rest.

For example, consider the mountain in the picture below, which has N = 6 landmarks. If your friends are in landmarks 5 and 2, you can visit both if you follow the sequence of landmarks 1 ↓ 2 ↑ 1 ↓ 3 ↓ 5, where a ↓ b means that you go down a track from landmark a to landmark b, and a ↑ b means that you climb a track from landmark a to landmark b. Another possible sequence is 1 ↓ 3 ↓ 5 ↑ 3 ↑ 1 ↓ 2.

 
Given the tracks between the landmarks, the energy required to climb them, and the landmarks where your friends are, compute the minimum total amount of energy required to visit all your friends from the top of the mountain.


Input


Output

The first line contains two integers N and F (1 ≤ F < N ≤ 10^5), representing respectively the number of landmarks and the number of your friends that are climbing the mountain. Landmarks are identified with distinct integers from 1 to N, being 1 the top of the mountain, where you initially are. Each of the next N − 1 lines describes a different track with three integers A, B and C, indicating that there is a track from A to B that goes down and requires an amount C of energy to be climbed (1 ≤ A ≤ N, 2 ≤ B ≤ N, A 6= B and 1 ≤ C ≤ 100). The next line contains F different integers L1,L2,...,LF (2 ≤ Li≤ N for i = 1,2,...,F) representing the landmarks where your friends are. You may assume that the tracks between landmarks are such that there exists exactly one route that goes down from the top of the mountain to each other landmark.


Sample Input
Sample input 1
6 2
1 2 2
2 4 2
1 3 3
3 6 3
3 5 1
5 2

Sample input 2
4 2
1 2 2
1 3 1
3 4 2
2 4

Sample input 3
4 2
1 4 1
1 3 1
4 2 2
2 4
Sample Output
Sample output 1
2

Sample output 2
2

Sample output 3
0
Problem Source
ICPC Latin American Regional ? 2014


从1节点开始 要走到f个节点 向下走不要消耗能量 向上走需要消耗能量 能量值为边的权值

两次dfs  第一次搜索有哪些点是必须要走到的  第二次记录从1节点到各节点的权值和

用总的权值和减去需要消耗能量最大的那个节点  即最后走到这个点就不需要再走了


#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>

#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define MAXN 200010
#define MAXM 100010
#define INF 99999999
#define ll __int64
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)

using namespace std;

int Read()
{
    char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    int x = 0;
    while (c >= '0' && c <= '9') {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x;
}

void Print(int a)
{
     if(a>9)
         Print(a/10);
     putchar(a%10+'0');
}

struct Edge
{
    int to,val,next;
}edge[MAXN];
int head[MAXN],tot;
void init()
{
    tot=0;
    MEM(head,-1);
}
void addedge(int u,int v,int w)
{
    edge[tot].to=v; edge[tot].next=head[u]; edge[tot].val=w; head[u]=tot++;
    edge[tot].to=u; edge[tot].next=head[v]; edge[tot].val=w; head[v]=tot++;
}
int n,m;
int vis[MAXN];
int dis[MAXN];
int ans;

void dfs(int u,int fa)//搜索哪些点要走到
{
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==fa) continue;
        dfs(v,u);
        if(vis[v])
            vis[u]=1;
    }
}

void dfs2(int u,int fa)//搜索求距离
{
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==fa) continue;
        dis[v]=dis[u]+edge[i].val;
        if(vis[v])
            ans+=edge[i].val;
        dfs2(v,u);
    }
}

int main()
{
//    fread;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        MEM(vis,0);
        for(int i=0;i<n-1;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
        }
        for(int i=0;i<m;i++)
        {
            int v;
            scanf("%d",&v);
            vis[v]=1;
        }
        ans=0;
        dis[1]=0;
        dfs(1,-1);
        dfs2(1,-1);
        int mx=-1;
        for(int i=1;i<=n;i++)
        {
//            cout<<"ii  "<<i<<"  dis  "<<dis[i]<<endl;
            if(vis[i])
                mx=max(mx,dis[i]);
        }
//        cout<<"ans  "<<ans<<"    "<<"mx   "<<mx<<endl;
        printf("%d\n",ans-mx);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值