zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    XMPP即时通讯资料记录
    iOS 图片裁剪与修改
    iOS开发xcode报错:"xxxxxx"has been modified since the precompiled header was built
    模糊数学课件(清晰易懂)
    几个可用于数据挖掘和统计分析的java库
    java中list集合的内容,如何使用像数据库中group by形式那样排序
    spark java 代码example
    spark 编程向导
    一个深度学习博客
    Selenium2(WebDriver)_如何判断WebElement元素对象是否存在
  • 原文地址:https://www.cnblogs.com/lwqq3/p/9183668.html
Copyright © 2011-2022 走看看