• 【[TJOI2017]城市】


    题目

    好像(noip)之前做某雅礼的题的时候看到过这道题的数据范围增强版

    当时那道题数据范围是(3e5)感觉神仙的一批

    这道题数据范围(5e3)那岂不是可以(O(n^2))水过

    有一点非常显然就是我们断开的那条边肯定是树的直径上的一条边,于是我们可以先来两遍树形(dp)求出子树内最长链,次长链,和子树外最长链

    这个时候树的直径就知道啦

    我们枚举断边,当然只断直径上的边

    之后得到了两个联通块,我们对这两个联通块求一下直径

    考虑连接哪两个点会使得新直径尽量小

    显然分别从这两个联通块里找到一个点,这个点到联通块内最远的点距离最小

    新直径就是(max{r_1,r_2,w+d_1+d_2})(r_1,r_2)是两个联通块的直径,(w)是断开的边的边权,(d_1,d_2)是联通块内最远的点距离最小的距离

    代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define maxn 5005
    #define LL long long
    inline int max(int a,int b) {return a>b?a:b;}
    inline int min(int a,int b) {return a<b?a:b;}
    inline int read()
    {
    	char c=getchar();int x=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    struct E{int v,nxt,w;}e[maxn<<1];
    int head[maxn],f[maxn],g[maxn],t[maxn],T[maxn],F[maxn],dp[maxn];
    int n,num,R,ans,root;
    inline void add(int x,int y,int z) {e[++num].v=y;e[num].w=z;e[num].nxt=head[x];head[x]=num;}
    void dfs(int x,int fa)
    {
    	f[x]=g[x]=0;
    	for(re int i=head[x];i;i=e[i].nxt)
    	if(e[i].v!=fa)
    	{
    		if(!fa&&root==e[i].v) continue;
    		dfs(e[i].v,x);
    		if(f[e[i].v]+e[i].w>f[x]) g[x]=f[x],f[x]=f[e[i].v]+e[i].w;
    			else if(f[e[i].v]+e[i].w>g[x]) g[x]=f[e[i].v]+e[i].w;
    				else if(g[e[i].v]+e[i].w>g[x]) g[x]=g[e[i].v]+e[i].w;
    	}
    }
    void redfs(int x,int fa)
    {
    	for(re int i=head[x];i;i=e[i].nxt)
    	if(e[i].v!=fa)
    	{
    		if(!fa&&root==e[i].v) continue;
    		t[e[i].v]=t[x]+e[i].w;
    		if(f[e[i].v]+e[i].w==f[x]) t[e[i].v]=max(t[e[i].v],g[x]+e[i].w);
    			else t[e[i].v]=max(t[e[i].v],f[x]+e[i].w);
    		redfs(e[i].v,x);
    	}
    	dp[x]=max(f[x],t[x]);
    }
    int find(int x,int fa)
    {
    	int k=dp[x];
    	for(re int i=head[x];i;i=e[i].nxt)
    	if(e[i].v!=fa)
    	{
    		if(!fa&&root==e[i].v) continue;
    		k=min(k,find(e[i].v,x));
    	}
    	return k;
    }
    void check(int x,int fa)
    {
    	for(re int i=head[x];i;i=e[i].nxt)
    	if(e[i].v!=fa)
    	{
    		if(T[e[i].v]+F[e[i].v]==R) 
    		{
    			root=e[i].v;
    			memset(t,0,sizeof(t));
    			dfs(e[i].v,x);redfs(e[i].v,x);
    			dfs(x,0);redfs(x,0);
    			int now=0;
    			for(re int j=1;j<=n;++j) now=max(now,f[j]+g[j]);
    			now=max(now,e[i].w+find(e[i].v,x)+find(x,0));
    			ans=min(ans,now);
    		}
    		check(e[i].v,x);
    	}
    }
    int main()
    {
    	n=read();int x,y,z;
    	for(re int i=1;i<n;i++) x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z);
    	dfs(1,0),redfs(1,0);
    	for(re int i=1;i<=n;i++) R=max(R,f[i]+g[i]);ans=R;
    	for(re int i=1;i<=n;i++) T[i]=t[i],F[i]=f[i];
    	check(1,0);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    【大数据云原生系列】大数据系统云原生渐进式演进最佳实践
    Apache Flink on K8s:四种运行模式,我该选择哪种?
    Istio 运维实战系列(2):让人头大的『无头服务』-上
    istio 常见的 10 个异常
    Prometheus Metrics 设计的最佳实践和应用实例,看这篇够了!
    腾讯会议大规模使用Kubernetes的技术实践
    腾讯云推出云原生etcd服务
    Regionals 2014 Asia
    HDU1754 I Hate It splay
    HNOI2002 营业额统计 splay
  • 原文地址:https://www.cnblogs.com/asuldb/p/10306324.html
Copyright © 2020-2023  润新知