bzoj 2599: [IOI2011]Race

来源:互联网 发布:python退出程序 exit 编辑:程序博客网 时间:2024/05/21 22:21

Description

给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小.

Input

第一行 两个整数 n, k
第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始)

Output

一个整数 表示最小边数量 如果不存在这样的路径 输出-1

Sample Input

4 3
0 1 1
1 2 2
1 3 4

Sample Output

2

好激动啊我过了IOI的题【虽然是水题】
考虑点分治。对于每棵树记录子节点到根的距离,用vx[x]来存储前面子树的子节点到根的路径中长度为x的最少经历的边数。
然后每次扫一遍更新下ANS就可以了
#include<cstdio>#include<algorithm>using namespace std;struct line{     int s,t;     int x;     int next;}a[400001];int head[200001];int edge;inline void add(int s,int t,int x){     a[edge].next=head[s];     head[s]=edge;     a[edge].s=s;     a[edge].t=t;     a[edge].x=x;}int mini,minx;int son[200001];bool v[200001];inline void find(int d,int fa,int s){ son[d]=0;     int i;     int tmp=0;     for(i=head[d];i!=0;i=a[i].next)     {          int t=a[i].t;          if(t!=fa&&!v[t])          {               find(t,d,s);               son[d]+=(son[t]+1);               tmp=max(tmp,son[t]+1);          }     }     int mx=max(tmp,s-tmp-1);     if(mx<minx||mx==minx&&d<mini)     {          minx=mx;          mini=d;     }}struct save{     int x,d;     bool operator <(save y)const     {          return x<y.x;     }}sx[200001];int dis[200001],dep[200001];int vx[2000001];int p,k;inline void dfs(int d,int fa){     int i;     for(i=head[d];i!=0;i=a[i].next)     {          int t=a[i].t;          if(t!=fa&&!v[t])          {               dis[t]=dis[d]+a[i].x;               dep[t]=dep[d]+1;               p++;               sx[p].x=dis[t];               sx[p].d=dep[t];               dfs(t,d);          }     }}int ans=2100000000;inline void solve(int d){ v[d]=true;     int i,j;     int l,r;     p=0;     int p1=0;     for(i=head[d];i!=0;i=a[i].next)     {          int t=a[i].t;          if(!v[t])          {               dis[t]=a[i].x;               dep[t]=1;               p++;               sx[p].x=dis[t];               sx[p].d=dep[t];               p1=p;               dfs(t,d);               for(j=p1;j<=p;j++)                    if(sx[j].x<k)                         if(vx[k-sx[j].x]!=2100000000)                              ans=min(vx[k-sx[j].x]+sx[j].d,ans);               for(j=p1;j<=p;j++)               {                    if(sx[j].x==k)                         ans=min(ans,sx[j].d);                    if(sx[j].x<=k)                         vx[sx[j].x]=min(vx[sx[j].x],sx[j].d);   }          }     }     for(i=1;i<=p;i++)          if(sx[i].x<=k)               vx[sx[i].x]=2100000000;     for(i=head[d];i!=0;i=a[i].next)     {          int t=a[i].t;          if(!v[t])          {               mini=0;               minx=2100000000;               find(t,d,son[t]);               int root=mini;               solve(root);          }     }}int main(){//freopen("data.in","r",stdin);//freopen("data.out","w",stdout);     int n;     scanf("%d%d",&n,&k);     int i;     int s,t,x;     for(i=1;i<=n-1;i++)     {          scanf("%d%d%d",&s,&t,&x);          s++;          t++;          edge++;          add(s,t,x);          edge++;          add(t,s,x);     }     mini=0;     minx=2100000000;     find(1,0,n);     int root=mini;     for(i=1;i<=2000000;i++)          vx[i]=2100000000;     solve(root);     if(ans==2100000000)          printf("-1\n");     else          printf("%d\n",ans);     return 0;}


0 0
原创粉丝点击