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; }
pain and happy in the cruel world.