zoukankan      html  css  js  c++  java
  • [POJ 1935] Journey

    Link:

    POJ1935 传送门

    Solution:

    一道吓唬人的水题

    注意这是一棵树,两点间仅有唯一的路径

    于是每个“关键点”和起点只有一条路径,想去起点另一棵子树上的节点必须要回到起点

    如果必须要回到起点,答案$res$就是除去无用边后整棵树总距离$*2$,

    因为不必回到起点,最终结果为$res-mx$,$mx$为距起点的最远点的距离

    除去无用边的方式:给每个“关键点”打上$vis$标记,这样最远点之后的点就不会被$dfs$到了

    Code:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <utility>
    #include <vector>
    
    using namespace std;
    typedef pair<int,int> P;
    #define X first
    #define Y second
    const int MAXN=5e4+10;
    vector<P> G[MAXN];
    int n,k,root,dist[MAXN],vis[MAXN],mx,res,x,y,z;
    
    void dfs(int u,int anc)
    {
        for(int i=0;i<G[u].size();i++)
        {
            int v=G[u][i].X;
            if(v==anc) continue;
            dist[v]=dist[u]+G[u][i].Y;
            dfs(v,u);
            if(vis[v]) vis[u]=true,res+=G[u][i].Y*2; //传递标记
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&root);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            G[x].push_back(P(y,z));G[y].push_back(P(x,z));
        }
        scanf("%d",&k);
        for(int i=1;i<=k;i++)
            scanf("%d",&x),vis[x]=true; //打上标记
        dfs(root,0);
        for(int i=1;i<=n;i++)
            if(vis[i]) mx=max(mx,dist[i]);
        printf("%d",res-mx);
        return 0;
    }

    Review:

    (1)对“树”这个条件中“两点之间只有一条路径”这个性质不够敏感,

    因此未能看出到达一棵子树的最远点后必须要回到起点再出发这一推论

    (2)除去无用边的方法很妙:设置$vis=true$,将更远的点截去

    同时传递$vis$的值来更新答案

  • 相关阅读:
    URL中“#”
    2、Distributed Optimization
    转:增强学习(二)----- 马尔可夫决策过程MDP
    转:强化学习(Reinforcement Learning)
    强化学习学习资料
    转:A Painless Q-learning Tutorial (一个 Q-learning 算法的简明教程)
    1、通过搜索进行问题求解
    CMOS与BIOS
    转:Spring-session & redis 子域名共享session
    基于 token 的认证应用
  • 原文地址:https://www.cnblogs.com/newera/p/9157523.html
Copyright © 2011-2022 走看看