• POJ-1741 Tree


    题面

    Description

    Give a tree with n vertices,each edge has a length(positive integer less than 1001).
    Define dist(u,v)=The min distance between node u and v.
    Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
    Write a program that will count how many pairs which are valid for a given tree.

    Input

    The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.
    The last test case is followed by two zeros.

    Output

    For each test case output the answer on a single line.

    Sample Input

    5 4
    1 2 3
    1 3 1
    1 4 2
    3 5 1
    0 0
    

    Sample Output

    8
    

    题意

    求路径长度不超过k的路径数

    题解

    点分治(淀粉质)入门题

    通过这篇文章已经简单对点分治入门了(https://blog.csdn.net/qq_39553725/article/details/77542223),知道了为什么要减去子树的答案,以及参数w的使用,这个题就是点分治的模板题了

    首先我们对于这种统计树上路径数量,能否找到一条路径的题,可以考虑点分治,因为儿子的信息可能对父亲结点没什么用,对于那种需要维护子节点的信息合并到父节点,需要用儿子的信息算出父节点的答案的题,我们可以用启发式合并或者是dsu on tree

    像这个题,直接套用点分治的板子,统计答案的时候先排序再two pointer扫一遍即可。

    代码

    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    struct node {
        int v; ll w;
        node() {}
        node(int v, ll w): v(v), w(w) {}
    };
    const int N = 1e5 + 50;
    const int inf = 1e9;
    vector<node> G[N];
    int sze[N];
    int msze[N];
    int S;
    int maxx;
    int vis[N];
    int root;
    void getroot(int u, int f) {
        sze[u] = 1;
        msze[u] = 0;
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i].v;
            if (vis[v] || v == f) continue;
            getroot(v, u);
            sze[u] += sze[v];
            msze[u] = max(msze[u], sze[v]);
        }
        msze[u] = max(msze[u], S - sze[u]);
        if (msze[u] < maxx) {
            maxx = msze[u];
            root = u;
        }
    }
    ll dis[N];
    int cnt = 0;
    ll k;
    void getdis(int u, int f, ll d) {
        dis[++cnt] = d;
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i].v;
            if (vis[v] || v == f) continue;
            getdis(v, u, d + G[u][i].w);
        }
    }
    ll calc(int u, ll w) {
        cnt = 0;
        getdis(u, 0, w);
        sort(dis + 1, dis + cnt + 1);
        int l = 1, r = cnt;
        ll ans = 0;
        while (l <= r) {
            if (dis[l] + dis[r] <= k) {
                ans += r - l;
                l++;
            }
            else r--;
        }
        return ans;
    }
    
    ll ans;
    void dfs(int u) {
        ans += calc(u, 0);
        vis[u] = 1;
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i].v;
            if (vis[v]) continue;
            ans -= calc(v, G[u][i].w);
            S = sze[v];
            root = 0;
            maxx = inf;
            getroot(v, 0);
            dfs(root);
        }
    }
    int main() {
        int n;
        while (scanf("%d%lld", &n, &k)) {
            if (n == 0 && k == 0) break;
            for (int i = 1; i <= n; i++) G[i].clear();
            for (int i = 1; i < n; i++) {
                int u, v; ll w;
                scanf("%d%d%lld", &u, &v, &w);
                G[u].push_back(node(v, w));
                G[v].push_back(node(u, w));
            }
            memset(vis, 0, sizeof(vis));
            cnt = 0;
            S = n;
            root = 0;
            maxx = inf;
            ans = 0;
            getroot(1, 0);
            dfs(root);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    

    多组数据注意要清空的有:

    1. vis数组
    2. 答案ans
    3. 树的vector
  • 相关阅读:
    图论算法之查找强分支
    图论算法之拓扑排序的简单代码
    图论算法之最短路径
    由函数符号找不到联想到的动态链接过程
    linux下cp覆盖原so文件时引起的段错误原因确定
    java 中能否使用 动态加载的类(Class.forName) 来做类型转换?
    为什么java不支持多重继承?
    static inner class 什么时候被加载
    thinking in java 读书笔记 --- overriding private method
    java List排序方法 Comparator和Comparable
  • 原文地址:https://www.cnblogs.com/artoriax/p/12206410.html
Copyright © 2020-2023  润新知