• [BZOJ4379][POI2015]Modernizacja autostrady[树的直径+换根dp]


    题意

    给定一棵 (n) 个节点的树,可以断掉一条边再连接任意两个点,询问新构成的树的直径的最小和最大值。

    (nleq 5 imes 10^5) .

    分析

    • 记断掉一条边之后两棵树的直径为 (A,B) ,最长直径为 (A+B+1) 最短为 (max{A ,B ,lceil frac{A}{2} ceil+lceil frac{B}{2} ceil +1}) .

    • 维护每个点不同子树的前3长链和向上的最长链、不同子树的前2长路径和向上子树的最长路径。

    • 这样枚举断掉一条边之后换根 (dp) 一下就可以求得父节点所在树的直径了。

    • 方案可以按照 (dfs) 找树的直径的方式构造答案。

    • 总时间复杂度为 (O(n))

    换根dp可以解决树断一条边以及不同根询问等问题。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define go(u) for(int i=head[u],v=e[i].to;i;i=e[i].last,v=e[i].to)
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define pb push_back
    #define re(x) memset(x,0,sizeof x)
    typedef long long LL;
    inline int gi(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch))	{if(ch=='-') f=-1;ch=getchar();}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
    	return x*f;
    }
    template<typename T>inline bool Max(T &a,T b){return a<b?a=b,1:0;}
    template<typename T>inline bool Min(T &a,T b){return b<a?a=b,1:0;}
    const int N=5e5 + 7,inf=0x3f3f3f3f;
    int n,edc=1,edg1,edg2,ans1=inf,ans2,ban[N<<1];
    int f1[N][3],f2[N],g1[N][2],g2[N],fu[N],f[N][4],g[N][3],head[N];
    struct edge{
    	int last,to;
    	edge(){}edge(int last,int to):last(last),to(to){}
    }e[N*2];
    void Add(int a,int b){
    	e[++edc]=edge(head[a],b),head[a]=edc;
    	e[++edc]=edge(head[b],a),head[b]=edc;
    }
    bool cmp(int x,int y){return x>y;}
    void dfs1(int u,int fa){
    	go(u)if(v^fa){
    		dfs1(v,u);
    		int x=fu[v];
    		if(x>g1[u][0]) g1[u][1]=g1[u][0],g1[u][0]=x;
    		else if(x>g1[u][1]) g1[u][1]=x;
    		
    		x=f1[v][0]+1;
    		if(x>f1[u][0]) f1[u][2]=f1[u][1],f1[u][1]=f1[u][0],f1[u][0]=x;
    		else if(x>f1[u][1]) f1[u][2]=f1[u][1],f1[u][1]=x;
    		else if(x>f1[u][2]) f1[u][2]=x;
    	}
    	fu[u]=max(g1[u][0],f1[u][0]+f1[u][1]);
    }
    void dfs2(int u,int fa){
    	for(int i=0;i<3;++i) f[u][i]=f1[u][i];f[u][3]=f2[u];sort(f[u],f[u]+4,cmp);
    	for(int i=0;i<2;++i) g[u][i]=g1[u][i];g[u][2]=g2[u];sort(g[u],g[u]+3,cmp);
    	go(u)if(v^fa){
    		int x=0,cnt=0;
    		for(int j=0,fg=0;j<4;++j){
    			if(f[u][j]==f1[v][0]+1&&!fg){fg=1;continue;}
    			x=f[u][j]; break;
    		}
    		f2[v]=x+1,x=0;
    		for(int j=0,fg=0;j<4;++j){
    			if(f[u][j]==f1[v][0]+1&&!fg) {fg=1;continue;}
    			x+=f[u][j];if(++cnt==2) break;
    		}
    		
    		for(int j=0,fg=0;j<3;++j){
    			if(g[u][j]==fu[v]&&!fg) {fg=1;continue;}
    		    Max(x,g[u][j]);break;
    		}
    		g2[v]=x;
    		
    		int tmp=max(max(x,fu[v]),(x+1)/2+(fu[v]+1)/2+1);
    		if(ans1>tmp) ans1=tmp,edg1=i;
    		
    		tmp=(x+fu[v]+1);
    		if(ans2<tmp) ans2=tmp,edg2=i;
    		
    		dfs2(v,u);
    	}
    }
    int fa[N],mx,cho,tp,tmp[N];
    void dfs(int u,int dis){
    	if(dis>=mx) mx=dis,cho=u;
    	go(u)if(v^fa[u]&&!ban[i]) fa[v]=u,dfs(v,dis+1);
    }
    int main(){
    	n=gi();
    	rep(i,1,n-1) Add(gi(),gi());
    	dfs1(1,0); dfs2(1,0);
    	
    	printf("%d %d %d",ans1,e[edg1].to,e[edg1^1].to);
    	ban[edg1]=ban[edg1^1]=1;
    	int x=e[edg1].to;dfs(x,0);
    	re(fa),x=cho,mx=0,dfs(x,0);tp=0;for(int i=cho;i;i=fa[i]) tmp[++tp]=i;printf(" %d",tmp[tp+1>>1]);
    	
    	re(fa),x=e[edg1^1].to,mx=0,dfs(x,0);
    	re(fa),x=cho,mx=0,dfs(x,0);tp=0;for(int i=cho;i;i=fa[i]) tmp[++tp]=i;printf(" %d
    ",tmp[tp+1>>1]);
    	
    	printf("%d %d %d",ans2,e[edg2].to,e[edg2^1].to);
    	ban[edg1]=ban[edg1^1]=0,ban[edg2]=ban[edg2^1]=1;
    	
    	re(fa),x=e[edg2].to,mx=0,dfs(x,0);printf(" %d",cho);
    	re(fa),x=e[edg2^1].to,mx=0,dfs(x,0);printf(" %d
    ",cho);
    	return 0;
    }
    
  • 相关阅读:
    [Express 5] Create a express 5 application with node 14
    [Bash] Batch Rename Every File in a Directory with zsh
    [CSS 3 + JS] Create a Function to Convert JS Numbers into CSS Hex Colors
    [Express] Handle Syncronous and Asyncronous Errors in Express
    [ML L12 N15] Regularization & Lasso Regression
    [CSS 3] Responsive Text with vw unit
    [XState] Guarded Transitions
    [XState] Drag and Drop example (data-state, attr in css)
    fckeditor如何能实现直接粘贴把图片上传到服务器中
    ckeditor如何能实现直接粘贴把图片上传到服务器中
  • 原文地址:https://www.cnblogs.com/yqgAKIOI/p/9838677.html
Copyright © 2020-2023  润新知