zoukankan      html  css  js  c++  java
  • 洛谷 1099 ( bzoj 1999 ) [Noip2007]Core树网的核

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1999

    《算法竞赛进阶指南》346页。https://www.cnblogs.com/shenben/p/5895325.html

    1.用随便一条直径算就行了。

      由题知所有直径都有交点。故有公共部分。

      如果分叉形状。核选在分叉后的地方,偏心距一定它是到直径的较远端点的距离。不然直径就不是最长的了。

        核选在分叉前的地方,偏心距一定比上述距离短。不然直径就不是最长的了。所以选在分叉前的地方一定更优。

        所有的分叉前的地方就是所有直径的公共部分。所以随便找一条直径求就行了。

    2.核在不超限的情况下越长越好。所以在直径上弄两个指针,枚举核就是O(n)的了。

     3.max( max( dis[k] ) , dis[ s~i ] , dis[ j~t ] ) ( k是 i ~ j 连出去的子树中的点 ) <==> max( max( dis[k] ) , dis[ s~i ] , dis[ j~t ] ) ( k是所有的点 )

      之所以等价是因为对于一段核,直径上别的部分连出去的子树中的点到直径的距离一定小于第一个式子中的三个部分。不然直径就不是最长的了。

      然后 max( dis[k] ) ( k是所有的点 ) 就是一个定值了!只要找一下上式后两个部分的min,最后和max( dis[k] )取个max就行了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=5e5+5;
    int n,s,head[N],xnt,fa[N],dis[N],ans,l0,l1;
    bool vis[N];
    struct Edge{
        int next,to,w;
        Edge(int n=0,int t=0,int w=0):next(n),to(t),w(w) {}
    }edge[N<<1];
    int rdn()
    {
        int ret=0,fx=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')fx=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')(ret*=10)+=ch-'0',ch=getchar();
        return ret*fx;
    }
    void add(int x,int y,int z)
    {
        edge[++xnt]=Edge(head[x],y,z);head[x]=xnt;
        edge[++xnt]=Edge(head[y],x,z);head[y]=xnt;
    }
    void dfs(int cr,int f)
    {
        for(int i=head[cr],v;i;i=edge[i].next)
            if((v=edge[i].to)!=f&&!vis[v])
            {
                dis[v]=dis[cr]+edge[i].w;
                fa[v]=cr;dfs(v,cr);
            }
    }
    int main()
    {
        n=rdn();s=rdn();int x,y,z;
        for(int i=1;i<n;i++)
        {
            x=rdn();y=rdn();z=rdn();
            add(x,y,z);
        }
        dfs(1,0);l0=1;
        for(int i=1;i<=n;i++)if(dis[i]>dis[l0])l0=i;
        dis[l0]=0;fa[l0]=0;dfs(l0,0);
        for(int i=1;i<=n;i++)if(dis[i]>dis[l1])l1=i;
        ans=0x7fffffff;int j=l1;
        for(int i=l1;i;i=fa[i])
        {
            vis[i]=1;
            while(j&&dis[i]-dis[fa[j]]<=s)j=fa[j];
            ans=min(ans,max(dis[l1]-dis[i],dis[j]));
        }
        for(int i=1;i<=n;i++)if(vis[i])dis[i]=0,dfs(i,0);
        for(int i=1;i<=n;i++)ans=max(ans,dis[i]);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    如何:为 Silverlight 客户端生成双工服务
    Microsoft Sync Framework 2.1 软件开发包 (SDK)
    Windows 下的安装phpMoAdmin
    asp.net安全检测工具 Padding Oracle 检测
    HTTP Basic Authentication for RESTFul Service
    Windows系统性能分析
    Windows Server AppFabric Management Pack for Operations Manager 2007
    Mongo Database 性能优化
    服务器未能识别 HTTP 标头 SOAPAction 的值
    TCP WAIT状态及其对繁忙的服务器的影响
  • 原文地址:https://www.cnblogs.com/Narh/p/9199650.html
Copyright © 2011-2022 走看看