October 2nd test solution to a problem (to be updated)

October 2nd test solution to a problem



$ T1 $:

Description meaning of the questions:

To a $ n $ nodes of the tree, the point has non-negative weights, you need to find two points paths do not intersect, so that they and the maximum length.

$ N \ 10 ^ $ 5


$ solution: $

The nature of the apparent diameter, the final two paths only two cases:

  1. Wherein a diameter of two paths
  2. The two paths have a diameter endpoint endpoint

So we find a $ DFS $ twice the diameter and the diameter of this record. Put this diameter marker (deleted), the diameter of each point from the start of the radial sides of the DP $ $ tree, to find the longest chain starting from each point on the diameter, and the diameter of the longest chain does not intersect (the even the longest diameter and the initial configuration answer). Then enumerate each point as a turning point (leaving a path from here diameter), find another optimal turning point, update the answer diameter!


$ code: $

ll ans,tot;
int n,tt,rt,id,mx;
ll a[100005];
ll d[100005];
ll s[100005];
ll v[100005];
int t[100005];
bool vis[100005];

struct su{
    int to,next;
}b[200005];
int tou[100005],top;

inline void dfs(int i){ //找直径
    vis[i]=1; if(d[i]>d[mx]) mx=i;
    for(rg j=tou[i];j;j=b[j].next){
        rg to=b[j].to; if(vis[to])continue;
        d[to]=d[i]+a[to]; dfs(to);
    } vis[i]=0;
}

inline bool find(int i,int x){ //开栈记录最长链
    vis[i]=1; t[++tt]=i; if(i==x) return 1;
    for(rg j=tou[i];j;j=b[j].next){
        rg to=b[j].to; if(vis[to])continue;
        d[to]=d[i]+a[to]; if(find(to,x))return 1;
    } vis[i]=0; --tt; return 0; //vis数组会保留对直径的标记
}

inline void dp(int i){ //找到从每个点出发的最长链
    vis[i]=1; d[i]=0;
    for(rg j=tou[i];j;j=b[j].next){
        rg to=b[j].to; if(vis[to])continue;
        dp(to); tot=max(tot,d[to]+d[i]+a[i]); //tot记录不与直径交的最长链
        d[i]=max(d[i],d[to]);
    } vis[i]=0; d[i]+=a[i]; tot=max(tot,d[i]);
}

int main(){
    n=qr();
    for(rg i=1;i<=n;++i) a[i]=qr();
    for(rg i=1;i<n;++i){
        rg x=qr(),y=qr();
        b[++top]=su{y,tou[x]}; tou[x]=top;
        b[++top]=su{x,tou[y]}; tou[y]=top;
    } d[1]=a[1]; dfs(1); rt=mx; mx=0; //找直径端点
    d[rt]=a[rt]; dfs(rt); id=mx; mx=0; //找直径
    find(rt,id); //标记直径
    for(rg i=1;i<=tt;++i){
        rg x=t[i]; s[i]=d[x];
        for(rg j=tou[x];j;j=b[j].next){ //从直径每个点出发
            rg to=b[j].to; if(vis[to])continue;
            dp(to); v[i]=max(v[i],d[to]); //树型dp
        }
    }ans=tot+s[tt]; tot=0;
    for(rg i=1;i<=tt;++i){ //计算最终答案
        ans=max(ans,tot-s[i-1]+v[i]+s[tt]);
        tot=max(tot,s[i]+v[i]);
    }
    printf("%lld\n",ans);
    return 0;
}


$ $ T2:

Description meaning of the questions:


$ solution: $


$ code: $



$ T3 $:

Description meaning of the questions:


$ solution: $


$ code: $

Guess you like

Origin www.cnblogs.com/812-xiao-wen/p/11617670.html