zoukankan      html  css  js  c++  java
  • POJ1935 Journey

    POJ1935 Journey
    Time Limit: 1000MS Memory Limit: 30000K
    Total Submissions: 1239 Accepted: 445

    Description

    There are n cities in Byteland (numbered from 1 to n), connected by bidirectional roads. The king of Byteland is not very generous, so there are only n-1 roads, but they connect the cities in such a way that it is possible to travel from each city to any other city. 
    One day, a traveller Byterider arrived in the city number k. He was planning to make a journey starting in the city k and visiting on his way cities m1 , m2 , ..., mj (not necessarily in this order) --the numbers m i are all different and they are also different from k. Byterider -- like every traveller -- has only a limited amount of money, so he would like to visit all the cities that he has planned to visit using the shortest possible path (starting in the city k). A path is one road or a sequence of roads, where every next road begins in the city where the previous one ends. Help Byterider to determine the length of the shortest path for his journey.

    Input

    The first line of the standard input contains two integers n and k separated by a single space (2 <= n <= 50000, 1 <= k <= n), n is the number of cities in Byteland and k is the number of the first city on Byterider's path. Each of the following n-1 lines contains the description of one road in Byteland. Line (i + 1) (for 1 <= i <= n-1) contains three integers ai , bi and di separated by single spaces (1 <= ai ; bi <= n, 1 <= di <= 1000), ai and bi are the cities connected by the road, and di is the length of the road. Line (n + 1) contains one integer j -- the number of cities which Byterider would like to visit (1 <= j <= n-1). The next line contains j different integers m i separated by single spaces -- the numbers of the cities that Byterider would like to visit (1 <= mi <= n, mi != k).

    Output

    The first and only line of the standard output should contain exactly one integer: the length of the shortest path for Byterider's journey.

    Sample Input

    4 2
    1 2 1
    4 2 2
    2 3 3
    2
    1 3

    Sample Output

    5

    *************************************************************

    题目大意:带边权的树,给点一个根,问从根出发遍历某些点,所需的最小花费。

    解题思路:按要求建立一棵树,然后每次读入要访问的点a,然后把a以及他祖先的点全部标记一下。然后被标记的所有点就形成一棵新的树,问题就被转化为:要访问这棵新的树的所有节点所需的最小花费。这个问题很容易解决。dp[s][k],当k==1时表示访问这个节点后人就不回来了,k==2表示访问这个节点的子树后人又回到该点。

    #include <stdio.h>
    #include <string.h>
    #include <vector>
    #define N 50005
    #define MIN(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    
    struct E
    {
        int ed,val;
        E(int a,int b):ed(a),val(b){}
    };
    vector<E>gra[N];
    int fa[N],flag[N],dp[N][2];
    int n,root;
    
    void ini(void)
    {
        memset(fa,0,sizeof(fa));
        memset(flag,0,sizeof(flag));
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
            gra[i].clear();
    }
    
    void dfs(int s,int f)
    {
        fa[s]=f;
        for(int i=0;i<gra[s].size();i++)
        {
            int t=gra[s][i].ed,v=gra[s][i].val;
            if(fa[t])continue;
            dfs(t,s);
        }
    }
    
    void to_flag(int s)
    {
        while(!flag[s])
        {
            flag[s]=1;
            s=fa[s];
        }
    }
    
    void dpt(int s)
    {
        for(int i=0;i<gra[s].size();i++)
        {
            int t=gra[s][i].ed;
            if(t==fa[s]||flag[t]==0)continue;
            dpt(t);
        }
        for(int i=0;i<gra[s].size();i++)
        {
            int t=gra[s][i].ed,v=gra[s][i].val;
            if(t==fa[s]||flag[t]==0)continue;
            dp[s][1]=MIN(dp[s][0]+dp[t][1]+v,dp[s][1]+dp[t][0]+2*v);
            dp[s][0]+=dp[t][0]+2*v;
        }
    }
    
    void re(void)
    {
        ini();
        for(int i=1;i<n;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            gra[a].push_back(E(b,c));
            gra[b].push_back(E(a,c));
        }
    }
    
    void run(void)
    {
        dfs(root,-1);
        int m;
        scanf("%d",&m);
        flag[root]=1;
        for(int i=1;i<=m;i++)
        {
            int a;
            scanf("%d",&a);
            to_flag(a);
        }
        dpt(root);
        printf("%d\n",dp[root][1]);
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&root)==2)
        {
            re();
            run();
        }
    }
    

      

  • 相关阅读:
    H5中canvas标签制作在线画板
    H5中标签Canvas实现图像动画
    H5中画图标签Canvas---画矩形,画线,画圆,渐变色,图形载入
    java 的反射机制
    maven的介绍
    000 关于IDEA的基本环境配置以及快速使用(git拉载程序,Jdk安装,tomcat部署,应用程序打包运行)
    H5视频播放器属性与API控件,以及对程序的解释
    HTML5 标签语法变化和使用概念
    H5的简介
    android驱动USB摄像头
  • 原文地址:https://www.cnblogs.com/Fatedayt/p/2185411.html
Copyright © 2011-2022 走看看