문제가 10 월 2 일 테스트 솔루션 (업데이트 예정)

문제가 10 월 2 일 테스트 솔루션



$ T1 $ :

질문에 대한 설명의 의미 :

트리의 $ n 개의 $ 노드, 요점은 음이 아닌 가중치를 가지고, 당신은 경로가 교차하지 않는 두 점을 찾을 필요가 그래서 그들은 최대 길이.

N $ \ 10 ^ 5 $


$ 솔루션 : $

명백한 직경의 성격, 마지막 두 경로 다음 두 가지 경우에만 :

  1. 상기 두 경로의 직경
  2. 두 경로는 직경 엔드 포인트를

그래서 우리는 두 배의 직경이 레코드의 직경 달러 (A $) DFS $를 찾을 수 있습니다. (이 직경 마커 (삭제), 민주당 $ $ 나무의 반경 측면의 시작부터 각 지점의 직경, 직경의 각 지점에서 시작하여 가장 긴 체인을 찾을 수와 교차하지 않는 긴 체인의 직경을 넣어 심지어 가장 긴 직경과 초기 구성 응답). 그런 전환점으로 각 지점을 열거 (여기 직경에서 길을 떠나), 또 다른 최적의 전환점을 찾을 응답 직경을 업데이트!


$ 코드 : $

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 :

질문에 대한 설명의 의미 :


$ 솔루션 : $


$ 코드 : $



$ T3 $ :

질문에 대한 설명의 의미 :


$ 솔루션 : $


$ 코드 : $

추천

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