zoukankan      html  css  js  c++  java
  • Gym 101915 G(贪心)

    传送门

    题面:

    G. Robots

    time limit per test

    5.0 s

    memory limit per test

    256 MB

    input

    standard input

    output

    standard output

    The Robotics Olympiad teams were competing in a contest.

    There was a tree drawn on the floor, consisting of n nodes and n - 1 edges. The nodes are numbered from 1 to n, and each edge has a weight. The tree is rooted at the first node. q teams are participating, and each team is given an integer xi. Their robot should start at node 1, and move in the following way until there are no valid moves left: From all the edges between the current node and it's children, go through the edge with the maximum value less than xi. Note that the robot can't move to the parent, only to children.

    However, the teams weren't able to program the robots to return to them after the contest, so they had to manually pick them up. Since the tree can be quite large, they need your help to determine where each robot ended it's movement.

    Input

    The first line contains a single integer T, the number of test cases.

    The first line of each test case contains two space-separated integers n and q. (1 ≤ n, q ≤ 105).

    The following n - 1 lines contain 3 integers ui, vi, wi. This means that there is an edge connecting nodes ui and vi, with weight wi. (1 ≤ ui, vi ≤ n) (1 ≤ wi ≤ 109). It's guaranteed that all wi are distinct.

    The following line contains q integers xi. (1 ≤ xi ≤ 109).

    Output

    For each test case, print one line with a single number Si, the sum of numbers of nodes where each robot ends.

    Example

    input 

    1
    5 7
    1 2 3
    1 3 4
    3 4 9
    3 5 7
    1 3 4 9 8 7 10
    

    output

    21
    

    Note

    In the sample test case, the robots end in the following nodes: {1, 1, 2, 5, 5, 3, 4}.

    Si = 1+1+2+5+5+3+4 = 21.

    Large I/O files. Please consider using fast input/output methods.

    题意:

        给出一棵边权互不相同且根为1的树,有q个机器人,每个机器人有个权值x,问,从根出发,只能往儿子走,每次会选择不超过x的最大的边走下去,如果不存在儿子或者不存在这样的边,则停止,问最终会停在哪个点,将所有询问的答案求和输出。

    题目分析:

        首先,对于每一个结点,你能不能往下走取决于从根到该结点的路径上的最大值,因此我们首先需要用dfs预处理出来根到每一个结点的最大值max。

        之后我们考虑如下的贪心策略:将所有的边权以及机器人的权值,均按从大大小进行排序。选取权值最大的机器人从根进行遍历,直到无法再向下延申。因为边权按照从大到小排序,因此对于该位置,若有a个机器人的权值大于当前结点的最大值max,则证明这a个机器人均会经过该点,此时我们只需要在此时对答案直接进行更新即可。之后不断遍历,直到所有机器人都用完即结束。

    代码:

    #include <bits/stdc++.h>
    #define maxn 100005
    using namespace std;
    struct edge{
        int to,w;
    };
    vector<edge>vec[maxn<<1];
    bool cmp(edge a,edge b){
        return a.w>b.w;
    }
    void add_edge(int from,int to,int w){
        edge tmp={to,w};
        vec[from].push_back(tmp);
        tmp={from,w};
        vec[to].push_back(tmp);
    }
    int maxx[maxn],vis[maxn];
    void init(int n){
        for(int i=0;i<=n;i++) vec[i].clear();
        memset(vis,0,sizeof(vis));
        memset(maxx,0,sizeof(maxx));
    }
    void Predfs(int x,int fa){//预处理出每个结点路径上的最大值
        for(int i=0;i<vec[x].size();i++){
            if(vec[x][i].to==fa) continue;
            maxx[vec[x][i].to]=max(vec[x][i].w,maxx[x]);
            Predfs(vec[x][i].to,x);
        }
    }
    priority_queue<int>que;
    void dfs(int x,long long  &ans){
        vis[x]=1;
        if(que.empty()) return ;
        if(que.top()<=maxx[x]) return ;
        for(int i=0;i<vec[x].size();i++){
            int to=vec[x][i].to;
            if(vis[to]) continue;
            if(vec[x][i].w<que.top()) dfs(to,ans);
        }
        while(que.top()>maxx[x]&&!que.empty()){
            ans+=x;
            que.pop();
        }
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--){
            int n,q;
            scanf("%d%d",&n,&q);
            init(n);
            for(int i=0;i<n-1;i++){
                int from,to,cost;
                scanf("%d%d%d",&from,&to,&cost);
                add_edge(from,to,cost);
            }
            while(q--){
                int num;
                scanf("%d",&num);
                que.push(num);
            }
            for(int i=1;i<=n;i++) sort(vec[i].begin(),vec[i].end(),cmp);
            Predfs(1,-1);
            long long  ans=0;
            dfs(1,ans);
            printf("%lld
    ",ans);
        }
    }
    
  • 相关阅读:
    【设计模式】适配器
    【c++算法】变序性算法
    【电信业务】【原则与规范】TMF的NGOSS
    【电信业务】【原则与规范】ITU的TMN
    【c++算法】排序算法
    家后
    【设计模式】桥接
    【电信业务】【原则与规范】SOA 面向服务架构
    UIImage转换成UIView
    ASIHTTPREQUEST网络加载图片
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007184.html
Copyright © 2011-2022 走看看