BZOJ2599: [IOI2011]Race

2599: [IOI2011]Race

Time Limit: 50 Sec  Memory Limit: 128 MB
Submit: 1401  Solved: 412
[Submit][Status]

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

题解:

居然1A了,还跑这么快233.。。。

有关树上路径我们可以考虑点分治。

假如我们当前正在处理以rt为根的树,那么路径统计的时候比较麻烦的就是在同一棵子树内的两个点。用g[i]表示达到i距离最小边数。

处理这个问题很简单,我们可以先用一棵子树的信息来更新答案,再用它的信息来更新我们的g数组。

就是这样,最后再做一遍还原即可。

inline void work(int x)
{
    v[x]=1;
    for(int i=head[x],y;i;i=e[i].next)if(!v[y=e[i].go])
    {
        cnt=0;
        getdep(y,x,e[i].w,1);
        for1(j,cnt)if(d[j][0]<=k)ans=min(ans,g[k-d[j][0]]+d[j][1]);
        for1(j,cnt)if(d[j][0]<=k)g[d[j][0]]=min(g[d[j][0]],d[j][1]);
    }
    ans=min(ans,g[k]);
    for(int i=head[x],y;i;i=e[i].next)if(!v[y=e[i].go])
    {
        cnt=0;
        getdep(y,x,e[i].w,1);
        for1(j,cnt)if(d[j][0]<=k)g[d[j][0]]=inf;
    }
    for(int i=head[x],y;i;i=e[i].next)if(!v[y=e[i].go])
    {
        sum=s[y];rt=0;
        getrt(y,x);
        work(rt);
    }
}

 

 

代码:

  1 #include<cstdio>
  2 
  3 #include<cstdlib>
  4 
  5 #include<cmath>
  6 
  7 #include<cstring>
  8 
  9 #include<algorithm>
 10 
 11 #include<iostream>
 12 
 13 #include<vector>
 14 
 15 #include<map>
 16 
 17 #include<set>
 18 
 19 #include<queue>
 20 
 21 #include<string>
 22 
 23 #define inf 1000000000
 24 
 25 #define maxn 200000+5
 26 
 27 #define maxm 2000000+5
 28 
 29 #define eps 1e-10
 30 
 31 #define ll long long
 32 
 33 #define pa pair<int,int>
 34 
 35 #define for0(i,n) for(int i=0;i<=(n);i++)
 36 
 37 #define for1(i,n) for(int i=1;i<=(n);i++)
 38 
 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 40 
 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 42 
 43 #define mod 1000000007
 44 
 45 using namespace std;
 46 
 47 inline int read()
 48 
 49 {
 50 
 51     int x=0,f=1;char ch=getchar();
 52 
 53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 54 
 55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 56 
 57     return x*f;
 58 
 59 }
 60 struct edge{int go,next,w;}e[2*maxn];
 61 int n,k,cnt,tot,sum,rt,ans=inf,f[maxn],g[maxm],d[maxn][2],head[maxn],s[maxn];
 62 bool v[maxn];
 63 inline void insert(int x,int y,int z)
 64 {
 65     e[++tot]=(edge){y,head[x],z};head[x]=tot;
 66     e[++tot]=(edge){x,head[y],z};head[y]=tot;
 67 }
 68 inline void getrt(int x,int fa)
 69 {
 70     s[x]=1;f[x]=0;
 71     for(int i=head[x],y;i;i=e[i].next)if(!v[y=e[i].go]&&y!=fa)
 72     {
 73         getrt(y,x);
 74         s[x]+=s[y];
 75         f[x]=max(f[x],s[y]);
 76     }
 77     f[x]=max(f[x],sum-f[x]);
 78     if(f[x]<f[rt])rt=x;
 79 }
 80 inline void getdep(int x,int fa,int w1,int w2)
 81 {
 82     d[++cnt][0]=w1;d[cnt][1]=w2;
 83     for(int i=head[x],y;i;i=e[i].next)if(!v[y=e[i].go]&&y!=fa)getdep(y,x,w1+e[i].w,w2+1);
 84 }        
 85 inline void work(int x)
 86 {
 87     v[x]=1;
 88     for(int i=head[x],y;i;i=e[i].next)if(!v[y=e[i].go])
 89     {
 90         cnt=0;
 91         getdep(y,x,e[i].w,1);
 92         for1(j,cnt)if(d[j][0]<=k)ans=min(ans,g[k-d[j][0]]+d[j][1]);
 93         for1(j,cnt)if(d[j][0]<=k)g[d[j][0]]=min(g[d[j][0]],d[j][1]);
 94     }
 95     ans=min(ans,g[k]);
 96     for(int i=head[x],y;i;i=e[i].next)if(!v[y=e[i].go])
 97     {
 98         cnt=0;
 99         getdep(y,x,e[i].w,1);
100         for1(j,cnt)if(d[j][0]<=k)g[d[j][0]]=inf;
101     }
102     for(int i=head[x],y;i;i=e[i].next)if(!v[y=e[i].go])
103     {
104         sum=s[y];rt=0;
105         getrt(y,x);
106         work(rt);
107     }
108 }
109 
110 int main()
111 
112 {
113 
114     freopen("input.txt","r",stdin);
115 
116     freopen("output.txt","w",stdout);
117 
118     n=read();k=read();
119     for0(i,k)g[i]=inf;
120     for1(i,n-1)
121     {
122         int x=read()+1,y=read()+1,z=read();insert(x,y,z);
123     }
124     f[rt=0]=inf;
125     sum=n;
126     getrt(1,0);
127     work(rt);
128     if(ans>=n)ans=-1;
129     cout<<ans<<endl;
130 
131     return 0;
132 
133 }  
View Code

 

 

posted @ 2014-12-18 15:01  ZYF-ZYF  Views(243)  Comments(0Edit  收藏  举报