bzoj 2599 [IOI2011]Race 点分

[IOI2011]Race

Time Limit: 70 Sec  Memory Limit: 128 MB
Submit: 4768  Solved: 1393
[Submit][Status][Discuss]

Description

给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, 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

HINT

 

 2018.1.3新加数据一组,未重测

 

点分治模板题

 

  1 #include<cstring>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<cmath>
  6 #include<queue>
  7 #include<map>
  8 
  9 #define ll long long
 10 #define inf 1000000007
 11 #define N 200007
 12 using namespace std;
 13 inline int read()
 14 {
 15     int x=0,f=1;char ch=getchar();
 16     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
 17     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
 18     return x*f;
 19 }
 20 
 21 int num=0;
 22 int n,k;
 23 int total,id,f[N],siz[N];
 24 ll tot,a[N];
 25 int bs[N];
 26 int ans=inf;
 27 bool vis[N];
 28 int cnt,hed[N],rea[N<<1],nxt[N<<1],val[N<<1];
 29 map<ll,int>p;
 30 
 31 void add(int u,int v,int z)
 32 {
 33     nxt[++cnt]=hed[u];
 34     hed[u]=cnt;
 35     rea[cnt]=v;
 36     val[cnt]=z;
 37 }
 38 void add_two_way(int x,int y,int z)
 39 {
 40     add(x,y,z);
 41     add(y,x,z);
 42 }
 43 void get_heart(int u,int fa)
 44 {
 45     siz[u]=1,f[u]=0;
 46     for (int i=hed[u];i!=-1;i=nxt[i])
 47     {
 48         int v=rea[i];
 49         if (v==fa||vis[v]) continue;
 50         get_heart(v,u);
 51         siz[u]+=siz[v],f[u]=max(f[u],siz[v]);
 52     }
 53     f[u]=max(f[u],total-siz[u]);
 54     if (f[u]<f[id]) id=u;
 55 }
 56 void dfs(int u,int fa)
 57 {
 58     int now=tot;
 59     if (a[tot]==k) ans=min(ans,bs[tot]);
 60     if (p[k-a[tot]]) ans=min(ans,p[k-a[tot]]+bs[tot]);
 61     for (int i=hed[u];i!=-1;i=nxt[i])
 62     {
 63         int v=rea[i],fee=val[i];
 64         if (fa==v||vis[v]) continue;
 65         bs[++tot]=bs[now]+1,a[tot]=a[now]+fee;
 66         dfs(v,u);
 67     }
 68 }
 69 void calc(int u)
 70 {
 71     map<ll,int>z;
 72     swap(p,z),bs[u]=0;
 73     for (int i=hed[u];i!=-1;i=nxt[i])
 74     {
 75         int v=rea[i],fee=val[i];
 76         if (vis[v]) continue;
 77         bs[++tot]=1,a[tot]=fee;
 78         dfs(v,u);
 79         for (int i=1;i<=tot;i++)
 80             if (!p[a[i]]) p[a[i]]=bs[i];
 81             else p[a[i]]=min(p[a[i]],bs[i]);
 82         tot=0;
 83     }
 84 }
 85 void solve(int u)
 86 {
 87     vis[u]=true;calc(u);int sum=total;
 88     for (int i=hed[u];i!=-1;i=nxt[i])
 89     {
 90         int v=rea[i];
 91         if (vis[v]) continue;
 92         total=(siz[v]>siz[u])?sum-siz[u]:siz[v];
 93         id=0,get_heart(v,u);
 94         solve(id);
 95     }
 96 }
 97 int main()
 98 {
 99     freopen("fzy.in","r",stdin);
100 //    freopen("fzy.out","w",stdout);
101     
102     memset(hed,-1,sizeof(hed));
103     n=read(),k=read();
104     for (int i=1;i<n;i++)
105     {
106         int x=read(),y=read(),z=read();x++,y++;
107         add_two_way(x,y,z);
108     }
109     total=f[0]=n;
110     get_heart(1,0);
111     solve(id);
112     if (ans==inf) puts("-1");
113     else printf("%d\n",ans);
114 }

 

posted @ 2018-04-15 15:23  Kaiser-  阅读(159)  评论(0编辑  收藏  举报