zoukankan      html  css  js  c++  java
  • 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

     

  • 相关阅读:
    绘图与滤镜全面解析
    排序算法——快速排序
    IOS QuartzCore核心动画框架
    const 笔记
    operation 多线程
    指针 总结
    问题 H: 老管家的忠诚(线段树)
    问题 H: 老管家的忠诚(线段树)
    Python——numpy(python programming)
    Python——numpy(python programming)
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4171768.html
Copyright © 2011-2022 走看看