zoukankan      html  css  js  c++  java
  • poj1985和poj1849(树的直径)

    题目传送门:poj1985

    树是连通无环图,树上任意两点之间的路径是唯一的。定义树上任 意两点u, v的距离为u到v路径上边权的和。树的直径MN为树上最长路 径,即点M和N是树上距离最远的两个点。

    题目就是寻找树的直径的版子题,两次dfs(第一次遍历根节点所到达的最远距离x点,第二次dfs从x到达最远距离y,这个就是树的直径),或者树形dp,我这里用到了树形dp;

    还要感谢石神对我的教导和更正,让我接触了树形dp;

    但这个题的代码就不给出了,因为在下面一题的代码中会体现。。

    题目:poj1849

    所以这里我不仅给出题目的答案,我们也来讨论一下每一种情况;

    假设只有1个机器人遍历树,且要求回到原点, 它最少需要走多少路?

    2 × ∑wi。

    若不用回到原点?

    2 × ∑wi−(从出发点所能到达的最远距离)。即 沿着最远距离走,过程中每个分叉走两遍。

    假设只有2个机器人遍历树,且要求回到原点, 它最少需要走多少 路?

    2 ×∑wi。

    若不用回到原点?

    2 ×∑wi−(树的直径)。

    这个题就是最后一种情况,

    分析:考虑从一个结点遍历整个树再回到原点需要把每个边计算两遍,这 里机器人不用回到出发点,所以两个机器人到达的点越远越好。 要使路程最近,若起点在树的直径上,则两辆车往不同的方向走, 直径上的边只用走一遍,其他的要走两遍。 若起点不在直径上,则两人一起走到直径上,再往不同的方向走。 这样最优解就是所有边×2−直径,因为直径只走了一次,而其他边 必走两遍。

    #include<algorithm>
    #include<bitset>
    #include<cctype>
    #include<cerrno>
    #include<clocale>
    #include<cmath>
    #include<complex>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<deque>
    #include<exception>
    #include<fstream>
    #include<functional>
    #include<limits>
    #include<list>
    #include<map>
    #include<iomanip>
    #include<ios>
    #include<iosfwd>
    #include<iostream>
    #include<istream>
    #include<ostream>
    #include<queue>
    #include<set>
    #include<sstream>
    #include<stack>
    #include<stdexcept>
    #include<streambuf>
    #include<string>
    #include<utility>
    #include<vector>
    #include<cwchar>
    #include<cwctype>
    using namespace std;
    const int maxn=4e4+10;
    template<typename T>inline void read(T &x)
    {
        x=0;
        T f=1,ch=getchar();
        while (!isdigit(ch) && ch^'-') ch=getchar();
        if (ch=='-') f=-1, ch=getchar();
        while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
        x*=f;
    }
    int n,m,a,b,c,point,tot,ans,sum;
    int dis[40000],vis[40000],lin[40000];
    struct gg {
        int y,next,v;
    }an[50000];
    void add(int x,int y,int z) {
        an[++tot].y=y;
        an[tot].v=z;
        an[tot].next=lin[x];
        lin[x]=tot;
    }
    inline int dp(int x)
    {
        vis[x]=1;
        for(int i=lin[x];i;i=an[i].next)
        {
            int y=an[i].y;
            if(vis[y]) continue;
            dp(y);
            ans=max(ans,dis[x]+dis[y]+an[i].v);
            dis[x]=max(dis[x],dis[y]+an[i].v);
        }
        return ans;
    }
    int main()
    {
        int sum=0;
        read(n);read(m);
        for(int i=1;i<n;i++)
        {
            read(a),read(b),read(c);
            add(a,b,c);
            add(b,a,c);
            sum+=c;
        }
        dp(1);
        printf("%d
    ",(sum<<1)-ans);
        return 0;
    }
  • 相关阅读:
    MySQL 抓包工具
    php安全配置记录和常见错误梳理
    Mongodb副本集+分片集群环境部署记录
    线上mongodb 数据库用户到期时间修改的操作记录
    Redis+TwemProxy(nutcracker)集群方案部署记录
    Linux下Redis主从复制以及SSDB主主复制环境部署记录
    以多个实例方式打开Notepad++
    什么才是程序员的核心竞争力?zz
    谈谈如何在面试中发掘程序猿的核心竞争力zz
    解决Android SDK Manager更新时出现问题
  • 原文地址:https://www.cnblogs.com/Tyouchie/p/10384379.html
Copyright © 2011-2022 走看看