zoukankan      html  css  js  c++  java
  • bzoj3124: [Sdoi2013]直径

    http://www.lydsy.com/JudgeOnline/problem.php?id=3124

    第一问:

    dfs1、dfs2

    dfs2中记录dis[i]表示点i距离最长链左端点的距离

    第二问:

    所有直径的交集一定是最长链上连续的一段

    dfs3记录最长链,

    从最长链上每个点i开始dfs4,记录能到达的非最长链点的最远距离mx

    如果mx==最长链-dis[i],更新交集的左端点

    如果mx==dis[i],找到交集的右端点,退出

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    typedef long long LL;
    #define N 200001
    
    int tot;
    int front[N],nxt[N<<1],to[N<<1],val[N<<1];
    
    LL mx,max_len;
    int wh;
    
    LL dis[N]; 
    
    int path[N],num;
    
    bool use[N];
    
    int cf[N];
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c))  c=getchar(); 
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar();  }
    }
    
    void add(int u,int v,int w)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; val[tot]=w;
    }
    
    void dfs1(int x,int y,LL d)
    {
        if(d>mx) mx=d,wh=x;
        for(int i=front[x];i;i=nxt[i])
        {
            if(to[i]==y) continue;
            dfs1(to[i],x,d+val[i]);
        }
    }
    
    void dfs2(int x,int y,LL d)
    {
        dis[x]=d;
        if(d>max_len) max_len=d,wh=x;
        for(int i=front[x];i;i=nxt[i])
        {
            if(to[i]==y) continue;
            dfs2(to[i],x,d+val[i]);
        }
    }
    
    void dfs3(int x,LL d)
    {
        path[++num]=x; 
        use[x]=true;
        for(int i=front[x];i;i=nxt[i])
        {
            if(dis[to[i]]==d-val[i]) dfs3(to[i],d-val[i]);
        }
    }
    
    void dfs4(int x,int y,LL d)
    {
        mx=max(mx,d);
        for(int i=front[x];i;i=nxt[i])
        {
            if(to[i]==y || use[to[i]]) continue;
            dfs4(to[i],x,d+val[i]);
        }
    }
    
    int main()
    {
        int n;
        read(n);
        int u,v,w;
        for(int i=1;i<n;++i)
        {
            read(u); read(v); read(w);
            add(u,v,w);
        }
        dfs1(1,0,0);
        dfs2(wh,0,0);
        cout<<max_len<<'
    ';
        dfs3(wh,max_len);
        int L=1,R=num;
        for(int i=2;i<num;++i)
        {
            mx=0;
            dfs4(path[i],0,0);
            if(mx==max_len-dis[path[i]]) L=i;
            if(mx==dis[path[i]]) { R=i; break; }
        }    
        cout<<R-L;
    }

    3124: [Sdoi2013]直径

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1261  Solved: 603
    [Submit][Status][Discuss]

    Description

    小Q最近学习了一些图论知识。根据课本,有如下定义。树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度。如果一棵树有N个节点,可以证明其有且仅有N-1 条边。 路径:一棵树上,任意两个节点之间最多有一条简单路径。我们用 dis(a,b)
    表示点a和点b的路径上各边长度之和。称dis(a,b)为a、b两个节点间的距离。  
     直径:一棵树上,最长的路径为树的直径。树的直径可能不是唯一的。 
    现在小Q想知道,对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。 

    Input

    第一行包含一个整数N,表示节点数。 
    接下来N-1行,每行三个整数a, b, c ,表示点 a和点b之间有一条长度为c
    的无向边。 

    Output

      
    共两行。第一行一个整数,表示直径的长度。第二行一个整数,表示被所有
    直径经过的边的数量。 

    Sample Input


    6
    3 1 1000
    1 4 10
    4 2 100
    4 5 50
    4 6 100

    Sample Output

    1110
    2


    【样例说明】
    直径共有两条,3 到2的路径和3到6的路径。这两条直径都经过边(3, 1)和边(1, 4)。

    HINT

    对于100%的测试数据:2≤N≤200000,所有点的编号都在1..N的范围内,

     

    边的权值≤10^9。

  • 相关阅读:
    双日历时间段选择控件—daterangepicker(汉化版)
    vue elementui table表格展开行每次只展开一行
    vue-pdf PDF文件预览
    async await
    vuex发送axios请求
    jq调用浏览器下载文件 window.open()
    禁止页面右键、选择、F12操作
    vue 点击一条消息跳转相应的页面且对应相应的大模块和办理状态
    vue-infinite-scroll 滚动加载下一页
    填写流程当前登录人可以填写除自己可填项外还可看到他前面经办人相关填写的内容,且经办人后面的不可见
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8038444.html
Copyright © 2011-2022 走看看