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

    3124: [Sdoi2013]直径

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1830  Solved: 882
    [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。

    Source

    [Submit][Status][Discuss]
    
    HOME Back

    题解

    直径的必须边一定是连续的一段。证明:假如有分开的,那么中间就有环,与树不符。所以是连续的一段。

    直径就两边dfs,找必须边就先尽量向下走,走到一端后尽量向上走。能走的条件:把直径当成根求深度,若分支深度等于直径剩余的长,则出现了直径分叉,不能继续走了。

    时间复杂度(O(n))

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read(){
        rg T data=0,w=1;rg char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
        for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
        return data*w;
    }
    template<class T>il T read(rg T&x) {return x=read<T>();}
    typedef long long ll;
    using namespace std;
    
    co int N=2e5+1;
    int n,p[N],q[N];
    bool v[N];
    ll d[N],f[N];
    vector<pair<int,int> > e[N];
    void dfs(int x,int&o){
    	v[x]=1;
    	for(unsigned i=0;i<e[x].size();++i){
    		int y=e[x][i].first,z=e[x][i].second;
    		if(v[y]) continue;
    		d[y]=d[x]+z;
    		p[y]=x;
    		dfs(y,o);
    	}
    	v[x]=0;
    	if(d[x]>d[o]) o=x;
    }
    int main(){
    	read(n);
    	for(int i=1,x,y,z;i<n;++i){
    		read(x),read(y),read(z);
    		e[x].push_back(make_pair(y,z)),e[y].push_back(make_pair(x,z));
    	}
    	int s=1;
    	dfs(1,s);
    	int t=s;
    	d[s]=p[s]=0;
    	dfs(s,t);
    	printf("%lld
    ",d[t]);
    	for(int i=t;i;i=p[i]){
    		v[i]=1;
    		q[p[i]]=i;
    	}
    	for(int x=t;x;x=p[x]){
    		f[x]=0;
    		for(unsigned i=0;i<e[x].size();++i){
    			int y=e[x][i].first,z=e[x][i].second;
    			if(v[y]) continue;
    			d[y]=z;
    			int w=y;
    			dfs(y,w);
    			f[x]=max(f[x],d[w]);
    		}
    	}
    	int i,ans=0;
    	for(i=s;i;i=q[i]) // down
    		if(d[t]-d[i]==f[i]) break;
    	for(;i;i=p[i]){ // up
    		if(d[i]==f[i]) break;
    		++ans;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    nginx配置虚拟主机
    nginx 中http协议的相关配置
    nginx的性能优化
    编译安装NGINX-1.21.0
    nginx命令使用
    编译安装NGINX1.16.1
    nginx: [emerg] getpwnam("nginx") failed
    swift选择类或结构体
    工具与网址
    WARNING: CPU: 0 PID: 1 at ./arch/x86/include/asm/fpu/internal.h:373
  • 原文地址:https://www.cnblogs.com/autoint/p/11010766.html
Copyright © 2011-2022 走看看