UOJ#298. 【CTSC2017】网络

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/82463852

传送门

题解:
先求直径,可以证明这条边一定连在直径的两个点上。

那么我们处理出每个直径往外延伸的最长距离,再结合在链上的长度,就可以很好的列出式子了。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int RLEN=1<<18|1;
inline char nc() {
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
    char ch=nc(); int i=0,f=1;
    while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
    while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
    return i*f;
}

const int N=2e5+50;
int n,m,A,B,X,L;
int g[N],nt[N],vt[N],w[N],ec;
int fa[N],on[N],q[N],a[N],b[N];
LL mx[N],d[N],lim[4];

inline void add(int x,int y,int z) {nt[++ec]=g[x]; g[x]=ec; vt[ec]=y; w[ec]=z;}
inline bool cmp1(const int &a,const int &b) {return mx[a]+d[a]<mx[b]+d[b];}
inline bool cmp2(const int &a,const int &b) {return mx[a]-d[a]<mx[b]-d[b];}
inline void dfs(int x,int y,LL z) {
    d[x]=z; fa[x]=y; if(d[x]>=d[X]) X=x;
    for(int e=g[x];e;e=nt[e])
        if(vt[e]!=y) dfs(vt[e],x,z+w[e]);
}
inline LL dfs2(int x,int y,LL z) {
    LL mx=z;
    for(int e=g[x];e;e=nt[e]) 
        if(vt[e]!=y) mx=max(mx,dfs2(vt[e],x,z+w[e]));
    return mx;
}
LL mxlen;
inline void dfs3(int x,int y,LL z) {
    if(z>=mxlen) X=x;
    for(int e=g[x];e;e=nt[e])
        if(vt[e]!=y && !on[vt[e]]) dfs3(vt[e],x,z+w[e]);
}

struct BIT_MAX {
    LL bit[N];  
    inline void init() {
        for(int i=1;i<=n;i++) bit[i]=-1e18;
    } 
    inline void inc(int pos,LL v) {
        for(int i=pos;i;i-=(i&(-i))) bit[i]=max(bit[i],v);
    }
    inline LL ask(int pos,LL v=-1e18) {
        for(int i=pos;i<=n;i+=(i&(-i))) v=max(v,bit[i]);
        return v;
    }
} bit[2];

inline bool check(LL k) {
    bit[0].init(); bit[1].init();
    lim[0]=lim[1]=lim[2]=lim[3]=-1e18;

    int j=m; 
    for(int i=1;i<=m;i++) {
        int u=b[i];
        while(j && mx[u]-d[u]>k-mx[a[j]]-d[a[j]]) {
            bit[0].inc(a[j],mx[a[j]]+d[a[j]]);
            bit[1].inc(a[j],mx[a[j]]-d[a[j]]);
            --j;
        }
        LL v0=bit[0].ask(u+1), v1=bit[1].ask(u+1);
        if(v0!=-1e18 && v1!=-1e18) {
            lim[0]=max(lim[0],v0+mx[u]+d[u]+L-k);
            lim[1]=max(lim[1],v1+mx[u]+d[u]+L-k);
            lim[2]=max(lim[2],v0+mx[u]-d[u]+L-k);
            lim[3]=max(lim[3],v1+mx[u]-d[u]+L-k);
        }
    }
    int h1=m+1, h2=0; d[h1]=1e18; d[h2]=-1e18;
    for(int i=m;i>=1;i--) {
        LL up=min(d[i]-lim[1],-lim[3]-d[i]); 
        LL low=max(lim[0]-d[i],lim[2]+d[i]);
        while(h2<m  && d[h2+1]<=up) ++h2;
        while(h1>1 && d[h1-1]>=low) --h1;
        while(h2 && d[h2]>up) --h2;
        while(h1<=m && d[h1]<low) ++h1;
        if(h2>=h1 && h2>=i) return true; 
    } return false;
}

int main() { 
    while((n=rd()) && (L=rd())) {
        ec=0; memset(g,0,sizeof(g)); 
        memset(on,0,sizeof(on));
        memset(d,0,sizeof(d));
        for(int i=1;i<n;i++) {
            int x=rd(), y=rd(), z=rd();
            add(x,y,z); add(y,x,z);
        } dfs(1,0,0);
        dfs(A=X,0,0); B=X; m=0;
        for(int i=B;i;i=fa[i]) q[++m]=i, on[i]=1;
        reverse(q+1,q+m+1);
        memcpy(mx,d,sizeof(mx));
        for(int i=1;i<=m;i++) d[i]=mx[q[i]];
        memset(mx,0,sizeof(mx));
        LL l=0, r=d[m], ans;
        for(int i=1;i<=m;i++) 
            for(int e=g[q[i]];e;e=nt[e])
                if(!on[vt[e]]) {
                    mx[i]=max(mx[i],dfs2(vt[e],q[i],w[e]));
                    mxlen=0; dfs3(vt[e],q[i],0); 
                    mxlen=0; l=max(l,(dfs3(A=X,0,0),mxlen));
                }
        for(int i=1;i<=m;i++) a[i]=i, b[i]=i;
        sort(a+1,a+m+1,cmp1);
        sort(b+1,b+m+1,cmp2);
        if(l>r) ans=l;
        while(l<=r) {
            LL mid=(l+r)>>1;
            if(check(mid)) ans=mid, r=mid-1;
            else l=mid+1;
        } cout<<ans<<'\n';
    }
}

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/82463852