[IOI 2011]Race

Description

给一棵树,每条边有非负权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, 1 <= K <= 1000000

Input

第一行 两个整数 n, k

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

Output

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

Sample Input

4 3

0 1 1

1 2 2

1 3 4

Sample Output

2

转载自Navi_Awson的博客:http://www.cnblogs.com/NaVi-Awson/p/7560921.html

%%%Navi_Gayson大佬

有这个链接就行了,懒得写题解zyys

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 struct Node
  7 {
  8   int next,to,dis;
  9 }edge[400001];
 10 int num,head[200001],f[1000001],ans,k;
 11 int size[200001],maxsize[200001],minsize,root,n;
 12 bool vis[200001];
 13 int gi()
 14 {
 15   char ch=getchar();
 16   int x=0;
 17   while (ch<'0'||ch>'9') ch=getchar();
 18   while (ch>='0'&&ch<='9')
 19     {
 20       x=x*10+ch-'0';
 21       ch=getchar();
 22     }
 23   return x;
 24 }
 25 void add(int u,int v,int dis)
 26 {
 27   num++;
 28   edge[num].next=head[u];
 29   head[u]=num;
 30   edge[num].to=v;
 31   edge[num].dis=dis;
 32 }
 33 void get_size(int x,int fa)
 34 {int i;
 35   size[x]=1;
 36   maxsize[x]=0;
 37   for (i=head[x];i;i=edge[i].next)
 38     {
 39       int v=edge[i].to;
 40       if (vis[v]==0&&v!=fa)
 41     {
 42       get_size(v,x);
 43       size[x]+=size[v];
 44       maxsize[x]=max(maxsize[x],size[v]);
 45     }
 46     }
 47 }
 48 void get_root(int r,int x,int fa)
 49 {int i;
 50   maxsize[x]=max(maxsize[x],size[r]-size[x]);
 51   if (maxsize[x]<minsize)
 52     {root=x;minsize=maxsize[x];}
 53   for (i=head[x];i;i=edge[i].next)
 54     {
 55       int v=edge[i].to;
 56       if (vis[v]==0&&v!=fa)
 57     {
 58       get_root(r,v,x);
 59     }
 60     }
 61 }
 62 void get_ans(int x,int fa,int cnt,int val)
 63 {int i;
 64   if (val>k) return;
 65   if (f[k-val]||k==val)
 66   ans=min(ans,f[k-val]+cnt);
 67   for (i=head[x];i;i=edge[i].next)
 68     {
 69       int v=edge[i].to;
 70       if (vis[v]==0&&v!=fa)
 71     {
 72       get_ans(v,x,cnt+1,val+edge[i].dis);
 73     }
 74     }
 75 }
 76 void get_update(int x,int fa,int cnt,int val)
 77 {int i;
 78   if (val>k) return;
 79   if (f[k]==0) f[k]=cnt;
 80   else f[k]=min(f[k],cnt);
 81   for (i=head[x];i;i=edge[i].next)
 82     {
 83       int v=edge[i].to;
 84       if (vis[v]==0&&v!=fa)
 85     {
 86       get_update(v,x,cnt+1,val+edge[i].dis);
 87     }
 88     }
 89 }
 90 void get_delete(int x,int fa,int cnt,int val)
 91 {int i;
 92   if (val>k) return;
 93   f[val]=0;
 94   for (i=head[x];i;i=edge[i].next)
 95     {
 96       int v=edge[i].to;
 97       if (vis[v]==0&&v!=fa)
 98     {
 99       get_delete(v,x,cnt+1,val+edge[i].dis);
100     }
101     }
102 }
103 void solve(int x)
104 {int i;
105    minsize=2e9;
106    get_size(x,0);
107    get_root(x,x,0);
108    vis[root]=1;
109    for (i=head[root];i;i=edge[i].next)
110      {
111        int v=edge[i].to;
112        if (vis[v]==0)
113      {
114        get_ans(v,root,1,0);
115        get_update(v,root,1,0);
116      }
117      }
118    for (i=head[root];i;i=edge[i].next)
119      {
120        int v=edge[i].to;
121        if (vis[v]==0)
122      {
123        get_delete(v,root,1,0);
124      }
125      }
126    for (i=head[root];i;i=edge[i].next)
127      {
128        int v=edge[i].to;
129        if (vis[v]==0)
130      {
131        solve(v);
132      }
133      }
134 }
135 int main()
136 {int i,u,v,w;
137   cin>>n>>k;
138   for (i=1;i<=n-1;i++)
139     {
140       u=gi();v=gi();w=gi();
141       u++;v++;
142       add(u,v,w);
143       add(v,u,w);
144     }
145   ans=2e9;
146   solve(1);
147   if (ans==2e9) cout<<-1;
148   else cout<<ans;
149 }

 

posted @ 2017-09-26 16:39  Z-Y-Y-S  阅读(275)  评论(2编辑  收藏  举报