zoukankan      html  css  js  c++  java
  • bzoj 2599: [IOI2011]Race (点分治 本地过了就是过了.jpg)

    题面:(复制别人的。。。)

    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
     
    这道题好像是权限题。。bzoj上看不到这道题更别说交了。。。
    写了半天结果交不了,样例过了就当过了吧。。QAQ
     
    思路:
    多建一个cnt数组表示权值为i的最小边长,得到每个点到根节点的边长和权值和然后逐个更新就好了。
     
    实现代码:
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int  M = 1e5 + 10;
    int n,k,cnt1,root,f[M],head[M],siz[M],cnt[M],dis[M],vis[M],sum,ans;
    
    struct node{
        int to,next,w;
    }e[M];
    
    void add(int u,int v,int w){
        e[++cnt1].to=v;e[cnt1].next=head[u];e[cnt1].w=w;head[u]=cnt1;
    }
    
    void get_root(int u,int fa){
        f[u] = 0; siz[u] = 1;
        for(int i = head[u];i;i=e[i].next){
            int v = e[i].to;
            if(v == fa||vis[v]) continue;
            get_root(v,u);
            siz[u] += siz[v];
            f[u] = max(f[u],siz[v]);
        }
        f[u] = max(sum-siz[u],f[u]);
        if(f[u] < f[root]) root = u;
    }
    
    void get_dis(int u,int fa,int dep){
        if(dis[u] >= 0&&dis[u] <= k) ans = min(ans,dep + cnt[k-dis[u]]);
        for(int i = head[u];i;i=e[i].next){
            int v = e[i].to;
            if(v==fa||vis[v]) continue;
            dis[v] = dis[u] + e[i].w;
            get_dis(v,u,dep+1);
        }
    }
    
    void cal(int u,int fa,int dep,int flag){
        if(dis[u] >= 0&&dis[u] <= k)  {
            if(flag) cnt[dis[u]] = min(dep,cnt[dis[u]]);
            else cnt[dis[u]] = n;
        }
        for(int i = head[u];i;i=e[i].next){
            int v = e[i].to;
            if(v==fa||vis[v]) continue;
            cal(v,u,dep+1,flag);
        }
    }
    
    void solve(int u){
        vis[u] = 1; cnt[0] = 0;
        for(int i = head[u];i;i=e[i].next){
            int v = e[i].to;
            if(vis[v]) continue;
            dis[v] = e[i].w;
            get_dis(v,0,1);
            cal(v,0,1,1);
        }
        for(int i = head[u];i;i=e[i].next){  //初始化
            int v = e[i].to;
            if(vis[v]) continue;
            cal(v,0,1,0);
        }
        for(int i = head[u];i;i = e[i].next){
            int v = e[i].to;
            if(vis[v]) continue;
            root = 0;
            sum = siz[v];
            get_root(v,0);
            solve(v);
        }
    }
    
    int main()
    {
        int a,b,c;
        scanf("%d%d",&n,&k);
        ans = n;cnt1=1;
        for(int i = 1;i < n;i ++){
            scanf("%d%d%d",&a,&b,&c);
            a++;b++;
            add(a,b,c); add(b,a,c);
        }
        for(int i = 1;i <= k;i ++) cnt[i] = n;
        root = 0;f[0] = n; sum = n;get_root(1,0);
        solve(root);
        printf("%d
    ",(ans==n)?-1:ans);
    }
  • 相关阅读:
    Java创建对象的几种方式
    Sqlserver建立Oracle的鏈接服務器
    千万级的大表!MySQL这样优化更好
    ConurrentHashMap和Hashtable的区别
    BTree和B+Tree详解
    为什么MySQL数据库索引选择使用B+树?
    网易跟贴这么火,背后的某个力量不可忽视
    知物由学 | 如何利用人工智能来对抗DDoS攻击?
    揭秘医疗安全防卫战:“我们仍在购买不安全的医疗设备”
    6月第5周业务风控关注 | 《网络安全等级保护条例(征求意见稿)》本周正式发布
  • 原文地址:https://www.cnblogs.com/kls123/p/9437800.html
Copyright © 2011-2022 走看看