CF GYM-101915-G. Robots(dfs+思维)

链接:http://codeforces.com/gym/101915/problem/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

Copy

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

output

Copy

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.

题意:给一颗顶点数为n的带权无向树,定点编号为1-n,有q个机器人,每个机器人带一个值,要求所有机器人从顶点1出发,机器人权值严格大于边权且只能向孩子节点反向才能移动。问所有机器人终点顶点编号和。

思路:根据题意可知每个机器人都有固定的一条线路,首先dfs计算出所有顶点到起点1的最大边权值,然后将所有边权和机器人都按从大到小排序,再次dfs遍历树,遍历时,当前最前面机器人权值大于当前边权则向下dfs。每当遍历完当前顶点的孩子节点或者叶节点时,把当前能走到当前节点的机器人(即机器人值 > 当前节点的最大边权值)删掉并更新答案,不断回溯直到所有机器人被删除。机器人操作可用优先队列实现。

比如样例,10走到节点4后被删除,9和8走到5后被删除...

代码:

#include<bits/stdc++.h>
#define N 100005
#define M 200005
using namespace std;
typedef long long ll;
int maxx[N];
struct edge
{
    int v,w;
    edge(int a,int b):v(a),w(b){}
    edge(){}
    friend bool operator <(edge a,edge b)
    {
        return a.w>b.w;
    }
};

vector<edge>V[N];
void addedge(int u,int v,int w)
{
    V[u].push_back(edge(v,w));
}

void cal(int x,int fa)
{
    for(int i=0;i<(int)V[x].size();i++)
    {
        int to=V[x][i].v;
        if(to==fa) continue;
        maxx[to]=max(maxx[x],V[x][i].w);
        cal(to,x);
    }
}

priority_queue<int,vector<int>,less<int> > pq;
int vis[N];
ll ans;
void dfs(int x)
{
    vis[x]=1;
    if(pq.empty() || pq.top()<=maxx[x]) return;
    for(int i=0;i<(int)V[x].size();i++)
    {
        int to=V[x][i].v;
        if(vis[to]) continue;
        if(pq.top()>V[x][i].w) dfs(to);
    }
    while(!pq.empty() && pq.top()>maxx[x])
    {
        ans+=x;
        pq.pop();
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(maxx,0,sizeof(maxx));
        memset(vis,0,sizeof(vis));
        int n,q;
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++) V[i].clear();
        for(int i=1;i<n;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        cal(1,-1);
        for(int i=1;i<=n;i++) sort(V[i].begin(),V[i].end());
        while(q--)
        {
            int x;
            scanf("%d",&x);
            pq.push(x);
        }

        ans=0;
        dfs(1);
        printf("%lld\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值