zoukankan      html  css  js  c++  java
  • Problem 1999. -- [Noip2007]Core树网的核

    树网的核

    Problem 1999. -- [Noip2007]Core树网的核

    1999: [Noip2007]Core树网的核

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 2514  Solved: 855
    [Submit][Status][Discuss]

    Description

    设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T为树网(treenetwork),其中V, E分别表示结点与边的集合,W表示各边长度的集合,并设T有n个结点。 路径:树网中任何两结点a,b都存在唯一的一条简单路径,用d(a,b)表示以a,b为端点的路径的长度,它是该路径上各边长度之和。我们称d(a,b)为a,b两结点间的距离。 一点v到一条路径P的距离为该点与P上的最近的结点的距离: d(v,P)=min{d(v,u),u为路径P上的结点}。 树网的直径:树网中最长的路径称为树网的直径。对于给定的树网T,直径不一定是唯一的,但可以证明:各直径的中点(不一定恰好是某个结点,可能在某条边的内部)是唯一的,我们称该点为树网的中心。 偏心距ECC(F):树网T中距路径F最远的结点到路径F的距离,即 。 任务:对于给定的树网T=(V, E,W)和非负整数s,求一个路径F,它是某直径上的一段路径(该路径两端均为树网中的结点),其长度不超过s(可以等于s),使偏心距ECC(F)最小。我们称这个路径为树网T=(V,E,W)的核(Core)。必要时,F可以退化为某个结点。一般来说,在上述定义下,核不一定只有一个,但最小偏心距是唯一的。 下面的图给出了树网的一个实例。图中,A-B与A-C是两条直径,长度均为20。点W是树网的中心,EF边的长度为5。如果指定s=11,则树网的核为路径DEFG(也可以取为路径DEF),偏心距为8。如果指定s=0(或s=1、s=2),则树网的核为结点F,偏心距为12。

    Input

    包含n行: 第1行,两个正整数n和s,中间用一个空格隔开。其中n为树网结点的个数,s为树网的核的长度的上界。设结点编号依次为1, 2, ..., n。 从第2行到第n行,每行给出3个用空格隔开的正整数,依次表示每一条边的两个端点编号和长度。例如,“2 4 7”表示连接结点2与4的边的长度为7。 所给的数据都是正确的,不必检验。

    Output

    只有一个非负整数,为指定意义下的最小偏心距。

    Sample Input

    5 2
    1 2 5
    2 3 2
    2 4 4
    2 5 3

    Sample Output

    5

    HINT

    对于70%的数据,n<=200000
    对于100%的数据:n<=500000, s<2^31, 所有权值<500

    ==============================================
    似乎SPOJ上加强版的数据...

    Source

    [Submit][Status][Discuss]
    
    HOME Back

    题解

    参照Yi Cai的题解。

    首先明确几个性质:

    1. 对于树中的任意一点,距离其最远的点一定是树的直径的某一端点。
    2. 所有的直径是等价的,即任意一条所能求出的该最小偏心距相等。

    于是我们可以用两次dfs求出直径。任取一个点找到离它最远的点r,再从r找到距离它最远的点l。l到r的路径就是直径。

    显然在长度不超过S的情况下,链最长最好。在l到r上维护尽可能长的链,找到左右端点到直径做右端点的较大值的最小值。然后由链上各个点出发,找到不经过直径上的点抵达的其他点的最大深度。这个最大深度和之前的最小值中较大的就是答案。

    为什么是整条直径上找最大深度,而不是在核上找呢?

    显然,如果这个深度最深的点不是从核中的点,那么它到核的距离必定小于核的端点到直径端点的距离。所以如果有个节点到核的距离小于核的端点到直径端点的距离,那么它必定是从核上延伸出去的。

    时间复杂度(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 SIZE=500010;
    int head[SIZE],ver[SIZE*2],Next[SIZE*2],edge[SIZE*2];
    int fa[SIZE],f[SIZE],d[SIZE],a[SIZE];
    int n,s,m,tot;
    bool v[SIZE];
    void add(int x,int y,int z){
    	ver[++tot]=y,Next[tot]=head[x],edge[tot]=z,head[x]=tot;
    }
    void dfs(int x){
    	for(int i=head[x];i;i=Next[i]){
    		if(ver[i]!=fa[x]){
    			fa[ver[i]]=x;
    			d[ver[i]]=d[x]+edge[i];
    			dfs(ver[i]);
    		}
    	}
    }
    void diameter(){
    	dfs(1);
    	int x=1;
    	for(int i=2;i<=n;++i)if(d[i]>d[x]) x=i;
    	d[x]=0;
    	memset(fa,0,sizeof fa);
    	dfs(x);
    	int y=1;
    	for(int i=2;i<=n;++i)if(d[i]>d[y]) y=i;
    	while(y!=x){
    		v[y]=1;
    		a[++m]=y;
    		y=fa[y];
    	}
    	v[x]=1;
    	a[++m]=x;
    }
    void treedp(int x){
    	v[x]=1;
    	for(int i=head[x];i;i=Next[i])
    		if(!v[ver[i]]){
    			treedp(ver[i]);
    			f[x]=max(f[x],f[ver[i]]+edge[i]);
    		}
    }
    int main(){
    	read(n),read(s);
    	for(int i=1,x,y,z;i<n;++i){
    		read(x),read(y),read(z);
    		add(x,y,z),add(y,x,z);
    	}
    	diameter();
    	for(int i=1;i<=m;++i) treedp(a[i]);
    	int ans=0x7fffffff,temp=0;
    	for(int i=1;i<=m;++i) temp=max(temp,f[a[i]]);
    	for(int i=m,j=m;i>=1;--i){
    		while(j>=1&&d[a[j]]-d[a[i]]<=s) --j;
    		ans=min(ans,max(temp,max(d[a[i]],d[a[1]]-d[a[j+1]])));
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    关于我对区块链和比特币的看法
    叙Windows平台下基于MBR和UEFI的bootkit(一)--以MBR为例
    动若脱兔:深入浅出angr--初步理解符号执行以及angr架构
    面经
    倚天屠龙(一):妙用IDA Pro--利用IDAPython编写调试插件
    初生牛犊:Windows下Anti-sandboxes技术探究
    浮生半日:探究Python字节码
    抽丝剥茧:理解Android权限机制
    自古套路得人心:安全岗面经(人生苦短,请勿入坑二进制)
    点击按钮,复制微信号代码
  • 原文地址:https://www.cnblogs.com/autoint/p/10922192.html
Copyright © 2011-2022 走看看