• BZOJ3124: [Sdoi2013]直径 (树形DP)


    题意:给一颗树 第一问求直径 第二问求有多少条边是所有直径都含有的

    题解:求直径就不说了 解第二问需要自己摸索出一些性质

       任意记录一条直径后 跑这条直径的每一个点

       如果以这个点不经过直径能到达最远的距离等于这个点到直径某端点的距离的话

       那么从这个点到直径这一端点的这一条链显然是不满足答案的

       于是我们可以设置两个端点l,r 维护能满足条件的地方

       最后答案就是r - l + 1个端点r - l条边

    #include <stdio.h>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    
    int n, rt, l, r, num;
    int pre[200005];
    int vis[200005];
    int to[400005];
    int val[400005];
    int nex[400005];
    int head[200005];
    int lian[200005];
    ll dis[200005];
    ll diss[200005];
    ll zd, ans1, ans2;
    
    void dfs(int x, int fa)
    {
        int c = head[x];
        for(int i = c; i; i = nex[i])
        {
            int v = to[i];
            if(v == fa) continue;
            dis[v] = dis[x] + (ll)val[i];
            if(dis[v] > zd) zd = dis[v], rt = v;
            pre[v] = x;
            dfs(v, x);
        }
    }
    
    void chain()
    {
        int x = rt;
        while(x != pre[l])
        {
            num++;
            vis[x] = 1;
            lian[num] = x;
            x = pre[x];
        }
    }
    
    void dfs1(int x, int fa)
    {
        int c = head[x];
        for(int i = c; i; i = nex[i])
        {
            int v = to[i];
            if(v == fa) continue;
            if(vis[v]) continue;
            diss[v] = diss[x] + (ll)val[i];
            if(diss[v] > zd) zd = diss[v];
            dfs1(v, x);
        }
    }
    
    int main()
    {
        scanf("%d", &n);
        int cnt = 0; zd = 0; num = 0;
        for(int i = 1; i < n; i++)
        {
            int u, v, o; scanf("%d%d%d", &u, &v, &o);
            to[++cnt] = v; nex[cnt] = head[u]; head[u] = cnt; val[cnt] = o;
            to[++cnt] = u; nex[cnt] = head[v]; head[v] = cnt; val[cnt] = o;
        }
        dfs(1, -1);
        l = rt; dis[l] = 0; zd = 0;
        pre[l] = -1;
        dfs(l, -1);
        r = rt;
        ans1 = zd;
        chain();
    
        int a1 = 1, a2 = num;
        for(int i = 1; i <= num; i++)
        {
            zd = 0;
            dfs1(lian[i], -1);
            if(dis[r] - dis[lian[i]] == zd) a1 = i;
            if(zd == dis[lian[i]])
            {
                a2 = i;
                break;
            }
        }
        printf("%lld
    %d
    ", ans1, a2 - a1);
        return 0;
    }
    View Code
  • 相关阅读:
    19.音乐查询l练习
    python用requests爬取新浪财经首页要闻
    关于Pyhton正则报错: sre_constants.error: nothing to repeat at position
    python中的字典
    Python flask jQuery ajax 上传文件
    python中与时间有关的对象-datetime、time、date
    python os模块之实现多层目录文件查找
    python 字符串格式化输出 %d,%s及 format函数, 数字百分化输出
    linux unbuntu 虚拟环境 安装沙盒virtualenv 、virtualenvwrapper
    python实现二分查找
  • 原文地址:https://www.cnblogs.com/lwqq3/p/9183668.html
Copyright © 2020-2023  润新知