zoukankan      html  css  js  c++  java
  • 题解-CodeForces835F Roads in the Kingdom

    Problem

    CodeForces-835F

    题意:求基环树删去环上任意一边后直径最小值,直径定义为所有点对最近距离的最大值

    Solution

    首先明确删去环上一点是不会影响树内直径的,所以应当先把所有树的直径求出来,这是树形Dp可以解决的,同时建议使用树形Dp,可以一次性求出接下来要用到的数据

    这是直径在树上的情况,接下来考虑直径从树开始,中途经过环,最后回到树的情况

    我们先把每个点向树里头能走的最远距离(也就是带权深度)(f[x])求出来,同时把环排成一行,放到栈里头(st[1])~(st[top]),同时把这个环边权的前缀和求出来,放到数组(pre)里面

    考虑删去边((st[d],st[d+1]))

    则最远点对((x,y))有这两种情况:

    • (case~1~(1leq xleq yleq d~or~d+1leq xleq yleq n): ans=f[x]-pre[x]+f[y]+pre[y])
    • (case~2~(1leq xleq d,d+1leq yleq n): ans=f[x]+pre[x]+f[y]-pre[y]+pre[n])

    由于我们需要快速求出删去每一条边的最远点对,所以可以考虑维护前缀后缀最大值:

    (gl_x=max{f_i-pre_iig|iin[1,x]})

    (gr_x=max{f_i-pre_iig|iin[x,n]})

    (hl_x=max{f_i+pre_iig|iin[1,x]})

    (hr_x=max{f_i+pre_iig|iin[x,n]})

    这样的话,最远距离(ans)可以转化为(ans=max(fl_d+hl_d,fr_{d+1}+hr_{d+1},pre_n-hl_d+gr_{d+1}))

    由于这是个环,记得特殊考虑删去边((top,1))

    还有一点需要注意,就是加起来的两个值不能在同一个地方取到,比如说(fl_2=f_1-pre_1,hl_2=f_1+pre_1),则(fl_2)(hl_2)加起来是没有意义的,需要舍去,所以我们对于每个数组还需要维护一个次大值

    (⊙v⊙)嗯,你没看错,就是八个数组

    Code

    如果需要解释的话,(get\_cir)是找环的,(dfs)是处理树的情况的,(work)是处理环的

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rg register
    
    template <typename _Tp> inline _Tp read(_Tp&x){
    	char c11=getchar(),ob=0;x=0;
    	while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')ob=1,c11=getchar();
    	while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
    }
    
    const int N=201000;const ll inf=0x3f3f3f3f3f3f3f3f;
    struct Edge{int v,nxt,w;}a[N<<1];
    int head[N],is[N],st[N],vis[N];
    ll f[N],pre[N];
    int gl[N],gr[N],hl[N],hr[N],hhl[N],hhr[N],ggl[N],ggr[N];
    int n,m,_,top;ll Ans;
    
    void get_cir(int x,int las){
    	if(vis[x]){
    		int p=top;
    		while(st[p]^x)--p;
    		for(rg int i=p;i<=top;++i)
    			is[st[i-p+1]=st[i]]=1;
    		st[0]=-1;top-=p-1;
    		return ;
    	}vis[st[++top]=x]=1;
    	for(int i=head[x];i&&~st[0];i=a[i].nxt)
    		if(a[i].v^las)get_cir(a[i].v,x);
    	if(~st[0])vis[st[top--]]=0;
    }
    
    void dfs(int x,int las){
    	ll sec=0ll;
    	for(int i=head[x];i;i=a[i].nxt)
    		if(!is[a[i].v]&&a[i].v^las){
    			dfs(a[i].v,x);f[a[i].v]+=a[i].w;
    			if(f[a[i].v]>=f[x])sec=f[x],f[x]=f[a[i].v];
    			else if(f[a[i].v]>sec)sec=f[a[i].v];
    		}
    	Ans=max(Ans,f[x]+sec);
    }
    
    inline ll G(int x){return x?f[st[x]]-pre[x]:-inf;}
    inline ll H(int x){return x?f[st[x]]+pre[x]:-inf;}
    
    void work(){
    	st[0]=st[top];
    	for(rg int x=1;x<=top;++x){
    		for(rg int i=head[st[x-1]];i;i=a[i].nxt)
    			if(a[i].v==st[x]){
    				pre[x]=pre[x-1]+a[i].w;
    				break;
    			}
    		dfs(st[x],0);
    	}
    	for(rg int i=1;i<=top;++i){
    		gl[i]=gl[i-1],ggl[i]=ggl[i-1];
    		hl[i]=hl[i-1],hhl[i]=hhl[i-1];
    		if(G(i)>G(gl[i]))ggl[i]=gl[i],gl[i]=i;
    		else if(G(i)>G(ggl[i]))ggl[i]=i;
    		if(H(i)>H(hl[i]))hhl[i]=hl[i],hl[i]=i;
    		else if(H(i)>H(hhl[i]))hhl[i]=i;
    	}
    	for(rg int i=top;i;--i){
    		gr[i]=gr[i+1],ggr[i]=ggr[i+1];
    		hr[i]=hr[i+1],hhr[i]=hhr[i+1];
    		if(G(i)>G(gr[i]))ggr[i]=gr[i],gr[i]=i;
    		else if(G(i)>G(ggr[i]))ggr[i]=i;
    		if(H(i)>H(hr[i]))hhr[i]=hr[i],hr[i]=i;
    		else if(H(i)>H(hhr[i]))hhr[i]=i;
    	}
    	ll ans;
    	if(hl[top]!=gl[top])ans=G(gl[top])+H(hl[top]);
    	else ans=max(G(ggl[top])+H(hl[top]),G(gl[top])+H(hhl[top]));
    	for(rg int i=1;i<top;++i){
    		ll val=pre[top]+H(hl[i])+G(gr[i+1]);
    		ll tmp;
    		if(gl[i]^hl[i])tmp=G(gl[i])+H(hl[i]);
    		else tmp=max(G(ggl[i])+H(hl[i]),G(gl[i])+H(hhl[i]));
    		val=max(val,tmp);++i;
    		if(gr[i]^hr[i])tmp=G(gr[i])+H(hr[i]);
    		else tmp=max(G(ggr[i])+H(hr[i]),G(gr[i])+H(hhr[i]));
    		val=max(val,tmp);--i;
    		ans=min(ans,val);
    	}cout<<max(ans,Ans)<<endl;
    }
    
    void init();void work();
    int main(){init();work();return 0;}
    
    void init(){
    	read(n);int u,v,w;
    	for(rg int i=1;i<=n;++i){
    		read(u),read(v),read(w);
    		a[++_].v=v,a[_].w=w,a[_].nxt=head[u],head[u]=_;
    		a[++_].v=u,a[_].w=w,a[_].nxt=head[v],head[v]=_;
    	}get_cir(1,1);
    }
    
  • 相关阅读:
    js 获取asp.net TextBox值
    项目笔记一
    如何取GridView中隐藏列的值
    使用bablepolyfill
    border: 0.5px
    选择查询固定位置的数据
    SQL用户数据库权限设置
    Java.1 HelloWorld的分析
    Java.2 面向对象
    【drupal实践】windows下drupal7.22develop版本安装
  • 原文地址:https://www.cnblogs.com/penth/p/9668498.html
Copyright © 2011-2022 走看看