UOJ 276 [2016] Tsinghua training soda

Link
first point partition, the center of gravity is not saved in the current path through the other end in the center of gravity, press \ (\ overline wk \) sort.
Dichotomy then answer with double pointer path for each sweep of the center of gravity, and maintains the \ (\ overline wk \) minimum path.
Be careful not to choose two paths from the same sub-tree, and so we have to maintain a (\ overline wk \) \ path of least from different sub-tree \ (\ overline wk \) the smallest path.

#include<cstdio>
#include<algorithm>
typedef long long i64;
const int N=50007,M=1000007;
int n,tot=1,All,root,cnt,num,head[N],ver[N<<1],next[N<<1],vis[N<<1],size[N],mx[N],st[N],ed[N];
i64 k,edge[N<<1],val[M];
struct node{i64 l;int d,r;}t[2][M];
int operator<(node a,node b){return a.l<b.l;}
int read(){int x;scanf("%d",&x);return x;}
i64 raed(){i64 x;scanf("%lld",&x);return x;}
void add(){int u=read(),v=read();i64 w=raed();ver[++tot]=v,next[tot]=head[u],edge[tot]=w,head[u]=tot,ver[++tot]=u,next[tot]=head[v],edge[tot]=w,head[v]=tot;}
void findroot(int u,int fa)
{
    size[u]=1,mx[u]=0;
    for(int i=head[u],v;i;i=next[i]) if(!vis[i]&&(v=ver[i])^fa) findroot(v,u),size[u]+=size[v],mx[u]=std::max(mx[u],size[v]);
    mx[u]=std::max(mx[u],All-size[u]),root=mx[u]<mx[root]? u:root;
}
void dfs(int u,int fa,i64 a,int b,int c)
{
    t[0][++num]=node{a,b,c},t[1][num]=node{-a,b,c};
    for(int i=head[u],v;i;i=next[i]) if(!vis[i]&&(v=ver[i])^fa) dfs(v,u,a+edge[i]-k,b+1,c);
}
void solve(int u)
{
    int id=++cnt;
    st[id]=num+1;
    for(int i=head[u];i;i=next[i]) if(!vis[i]) dfs(ver[i],u,edge[i]-k,1,ver[i]);
    ed[id]=num;
    for(int i=0;i<2;++i) std::sort(t[i]+st[id],t[i]+ed[id]+1);
    for(int i=head[u],v;i;i=next[i]) if(!vis[i]) vis[i^1]=1,mx[0]=All=size[v=ver[i]],findroot(v,root=0),solve(root);
}
int check(i64 lim)
{
    for(int i=0;i<2;++i)
    {
    for(int j=1;j<=num;++j)
    {
        val[j]=-t[i][j].l-lim*t[i][j].d;
        if(t[i][j].l<=0&&val[j]<0) return 1;
    }
    for(int j=1;j<=cnt;++j)
    {
        int id1=0,id2=0;i64 mx1,mx2;
        for(int l=st[j],r=ed[j],p=l,q=r;q>=l;--q)
        {
        for(;p<=r&&t[i][q].l+t[i][p].l<=0;++p)
        {
            int id=t[i][p].r;i64 x=val[p];
            if(id1==id) { if(mx1>x) mx1=x; }
            else if(!id1||mx1>x) id2=id1,mx2=mx1,id1=id,mx1=x;
            else if(!id2||mx2>x) id2=id,mx2=x;
        }
        if(id1&&id1^t[i][q].r&&val[q]+mx1<0) return 1;
        if(id2&&id2^t[i][q].r&&val[q]+mx2<0) return 1;
        }
    }
    }
    return 0;
}
int main()
{
    n=read(),k=raed();i64 l=1,r=1e13;
    for(int i=1;i<n;++i) add();
    mx[0]=All=n,findroot(1,0),solve(root);
    for(i64 mid;l<=r;) check(mid=(l+r)>>1)? r=mid-1:l=mid+1;
    printf("%lld",r);
}

Guess you like

Origin www.cnblogs.com/cjoierShiina-Mashiro/p/12305676.html