• BZOJ2599:[IOI2011]Race(点分治)


    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

    Solution

    开一个100W的数组t,t[i]表示到当前处理的树的根距离为i的最小边数
    对于点x,我们要统计经过x的路径的话
    就分别统计x的每颗子树,在统计一颗子树的时候用t[i]更新答案
    并在每统计完一颗子树后更新t数组
    ↑这样是为了防止统计答案的时候两个点在同一子树里

    Code

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #define N (200000+100)
      5 using namespace std;
      6 struct node
      7 {
      8     int to,next,len;
      9 }edge[N*2];
     10 int n,k,sum,root,ans,INF;
     11 int head[N],num_edge;
     12 int depth[N],d[N],size[N],maxn[N];
     13 int dis[N],t[N*5];
     14 bool vis[N];
     15 
     16 void add(int u,int v,int l)
     17 {
     18     edge[++num_edge].to=v;
     19     edge[num_edge].len=l;
     20     edge[num_edge].next=head[u];
     21     head[u]=num_edge;
     22 }
     23 
     24 void Get_root(int x,int fa)
     25 {
     26     size[x]=1; maxn[x]=0;
     27     for (int i=head[x];i!=0;i=edge[i].next)
     28         if (edge[i].to!=fa && !vis[edge[i].to])
     29         {
     30             Get_root(edge[i].to,x);
     31             size[x]+=size[edge[i].to];
     32             maxn[x]=max(maxn[x],size[edge[i].to]);
     33         }
     34     maxn[x]=max(maxn[x],sum-size[x]);
     35     if (maxn[x]<maxn[root]) root=x;
     36 }
     37 
     38 void Calc(int x,int fa)
     39 {
     40     if (dis[x]<=k) ans=min(ans,depth[x]+t[k-dis[x]]);
     41     for (int i=head[x];i!=0;i=edge[i].next)
     42         if (!vis[edge[i].to] && edge[i].to!=fa)
     43         {
     44             dis[edge[i].to]=dis[x]+edge[i].len;
     45             depth[edge[i].to]=depth[x]+1;
     46             Calc(edge[i].to,x);
     47         }
     48 }
     49 
     50 void Reset(int x,int fa,int flag)
     51 {
     52     if (dis[x]<=k)
     53     {
     54         if (flag) t[dis[x]]=min(t[dis[x]],depth[x]);
     55         else t[dis[x]]=INF;
     56     }
     57     for (int i=head[x];i!=0;i=edge[i].next)
     58         if (edge[i].to!=fa && !vis[edge[i].to])
     59             Reset(edge[i].to,x,flag);
     60 }
     61 
     62 void Solve(int x)
     63 {
     64     vis[x]=true; t[0]=0;
     65     for (int i=head[x];i!=0;i=edge[i].next)
     66         if (!vis[edge[i].to])
     67         {
     68             depth[edge[i].to]=1;
     69             dis[edge[i].to]=edge[i].len;
     70             Calc(edge[i].to,0);
     71             Reset(edge[i].to,0,1);
     72         }
     73     for (int i=head[x];i!=0;i=edge[i].next) 
     74         if (!vis[edge[i].to])
     75             Reset(edge[i].to,0,0);
     76     for (int i=head[x];i!=0;i=edge[i].next)
     77         if (!vis[edge[i].to])
     78         {
     79             sum=size[edge[i].to];
     80             root=0;
     81             Get_root(edge[i].to,0);
     82             Solve(root);
     83         }
     84     
     85 }
     86 
     87 int main()
     88 {
     89     int u,v,l;
     90     memset(t,0x3f,sizeof(t));
     91     memset(&INF,0x3f,sizeof(INF));
     92     scanf("%d%d",&n,&k);
     93     for (int i=1;i<=n-1;++i)
     94     {
     95         scanf("%d%d%d",&u,&v,&l);
     96         u++; v++;
     97         add(u,v,l); add(v,u,l);
     98     }
     99     ans=sum=maxn[0]=n;
    100     Get_root(1,0);
    101     Solve(root);
    102     printf("%d",ans==n?-1:ans);
    103 }
  • 相关阅读:
    Annotation Type ManyToMany->>>>>Oracle
    windows 控制台默认为UTF-8显示的方法
    springboot读取配置文件
    Spring Boot配置文件放在jar外部
    Vue自定义过滤器
    vue中limitBy,filterBy,orderBy的用法
    track-by的使用
    Vue的computed属性
    vue实现百度下拉框
    Cas服务器以及客户端搭建
  • 原文地址:https://www.cnblogs.com/refun/p/8684117.html
Copyright © 2020-2023  润新知