bzoj2599: [IOI2011]Race

就和上一题差不多嗟

波老师说nlogn^2跑的过去,我想着还是优越点写个nlogn吧

用开1000000个vector记录下边权和为d的方案

然后出来一个个匹配就好啦~

 

然鹅。。。。

bzoj跑不过去,luogu开O2跑得贼快,CH也过了


ORZ肉老师,不用把全部记录的,就把边权和为d的方案中,属于不同子树的最小值和次小值记下来就行了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int n,K;
struct node
{
    int x,y,d,next;
}a[410000];int len,last[210000];
void ins(int x,int y,int d)
{
    len++;
    a[len].x=x;a[len].y=y;a[len].d=d;
    a[len].next=last[x];last[x]=len;
}

int rt,sum,tot[210000],G[210000];
bool v[210000];
void getrt(int x,int fr)
{
    G[x]=0;tot[x]=1;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(y!=fr&&v[y]==false)
        {
            getrt(y,x);
            G[x]=max(G[x],tot[y]);
            tot[x]+=tot[y];
        }
    }
    G[x]=max(G[x],sum-tot[x]);
    if(rt==0||G[rt]>G[x])rt=x;
}

//--------------------------

struct zz
{
    int bel,d,ad;
    zz(){}
    void init(){bel=-1;ad=2147483647;}
}z[210000];int zlen;
zz vec[1000010][2]; int tim,ti[1000010];
void vecpush(int d)
{
    if(vec[d][0].ad>z[zlen].ad)
    {
        zz t=vec[d][0];
        vec[d][0]=z[zlen];
        if(vec[d][0].bel!=t.bel)vec[d][1]=t;
    }
    else if(vec[d][1].ad>z[zlen].ad&&z[zlen].bel!=vec[d][0].bel)
        vec[d][1]=z[zlen];
}
void getd(int x,int fr,int bel,int d,int dep)
{
    if(d>K)return ;
    zlen++;
    z[zlen].bel=bel;z[zlen].d=d;z[zlen].ad=dep;
    
    if(ti[d]!=tim)
    {
        ti[d]=tim;
        vec[d][0].init(),vec[d][1].init();
    }
    vecpush(d);
    
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(y!=fr&&v[y]==false)getd(y,x,bel,d+a[k].d,dep+1);
    }
}
int mmin;
void calc(int x)
{
    zlen=0; tim++;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(v[y]==false)getd(y,x,y,a[k].d,1);
    }
    for(int i=1;i<=zlen;i++)
    {
        int j=K-z[i].d;
        if(z[i].d<=K/2&&ti[j]==tim)
        {
            if(z[i].bel!=vec[j][0].bel&&vec[j][0].bel!=-1)mmin=min(mmin,z[i].ad+vec[j][0].ad);
            else if(vec[j][1].bel!=-1)mmin=min(mmin,z[i].ad+vec[j][1].ad);
        }
        if(z[i].d==K)mmin=min(mmin,z[i].ad);
    }
}

//---------------------------

void divi(int x)
{
    v[x]=true;calc(x);
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(v[y]==false)
        {
            rt=0;sum=tot[y];
            getrt(y,x);
            divi(rt);
        }
    }
}


int main()
{
    freopen("race.in","r",stdin);
    freopen("race.out","w",stdout);
    scanf("%d%d",&n,&K);
    len=0;memset(last,0,sizeof(last));
    int x,y,d;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d%d",&x,&y,&d);x++;y++;
        ins(x,y,d);ins(y,x,d);
    }
    rt=0;sum=n;
    memset(v,false,sizeof(v));
    getrt(1,0);
    
    mmin=2147483647;tim=0;
    divi(rt);
    if(mmin==2147483647)printf("-1\n");
    else printf("%d\n",mmin);
    
    return 0;
}

 

posted @ 2018-08-09 11:28  AKCqhzdy  阅读(156)  评论(0编辑  收藏  举报