zoukankan      html  css  js  c++  java
  • bzoj2599

    2599: [IOI2011]Race

    Time Limit: 70 Sec  Memory Limit: 128 MB
    Submit: 2476  Solved: 733
    [Submit][Status][Discuss]

    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

    HINT

     

    Source

     题解:
      随便点分治,用一个ans[i]代表u,v距离为k,边数为i的点对个数,那么答案就为i (ans[i]>0 && i 最小);
      怎么求ans? 自己yy一下吧
    代码:
      
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #define N 200100  
    using namespace std;
    int tot,n,m,all,k,root,sum;
    int pre[N*2],v[N*2],val[N*2],now[N],size[N],ans[N],f[N];
    bool vis[N];
    struct data{int val,size;
    }d[N],da[N];
    bool cmp(data a,data b)
    {
        return a.val<b.val;
    }
    int read()
    {
        int x=0; char ch; bool bo=1;
        while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') bo=0;
        while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');
        if (!bo) return -x; return x;
    }
    void ins(int a,int b,int c)
    {
        ++tot; pre[tot]=now[a]; now[a]=tot; v[tot]=b; val[tot]=c;
    }
    void getroot(int u,int fa)
    {
        size[u]=1; f[u]=0;
        for (int p=now[u]; p; p=pre[p])
        {
            int son=v[p];
            if (vis[son]||son==fa) continue;
            getroot(son,u);
            size[u]+=size[son];
            f[u]=max(f[u],size[son]);
        }
        f[u]=max(f[u],all-size[u]);
        if (f[u]<f[root]) root=u;
    }
    void getarray(int u,int fa)
    {
        for (int p=now[u]; p; p=pre[p])
        {
            int son=v[p];
            if (son==fa||vis[son]) continue;
            da[++sum].val=d[son].val=d[u].val+val[p]; 
            da[sum].size=d[son].size=d[u].size+1;
            getarray(son,u);
        }
        
    }
    void calc(int u,int value, int f)
    {
        d[u].val=value; if (f==1) d[u].size=0; else d[u].size=1; 
        sum=0; da[++sum].val=value; da[sum].size=d[u].size;
        getarray(u,0);
        sort(da+1,da+1+sum,cmp);
        for (int i=1,j=sum; i<=j; i++)
        {
            while (j>i && da[j].val+da[i].val>k) j--;
            for (int p=j; da[i].val+da[p].val==k ;p--)ans[da[p].size+da[i].size]+=f;
        }
    }
    void solve(int u)
    {
        vis[u]=1; calc(u,0,1);
        for    (int p=now[u]; p; p=pre[p])
        {
            int son=v[p];
            if (vis[son]) continue;
            calc(son,val[p],-1);
            all=size[son]; 
            root=0; getroot(son,0);
            solve(root);
        }
    }
    int main()
    {
        n=read(); k=read();
        for (int i=1; i<n; i++)
        {
            int u=read()+1,v=read()+1,value=read();
            ins(u,v,value); ins(v,u,value);
        }
        all=n; f[root=0]=n; getroot(1,0); 
        solve(root);
        for (int i=1; i<n; i++)
        {
            if (ans[i]) 
            {
                printf("%d
    ",i);
                return 0;
            }
        }
        printf("-1
    "); return 0;
    } 
    View Code
  • 相关阅读:
    C# this关键字的四种用法
    MVC Html.AntiForgeryToken() 防止CSRF攻击
    简单的C#网络爬虫
    string format的各类格式及用法
    选取两个有序数组中最大的K个值,降序存入另一个数组中
    程序员面试:青蛙跳台阶问题(变态跳台阶)
    贪心算法,递归算法,动态规划算法比较与总结
    storm简介[ZZ]
    逻辑回归:使用SGD(Stochastic Gradient Descent)进行大规模机器学习
    mahout分类
  • 原文地址:https://www.cnblogs.com/HQHQ/p/5469111.html
Copyright © 2011-2022 走看看