• poj 1741 Tree(点分治)


    题目链接:http://poj.org/problem?id=1741

    题解:一道点分治的模版题,直线上的分治就没什么好说了简单的这是一道树上的分治模版题

    其实分治就是和二分差不多,树上的分治也就是不断的找树的重心然后再找经过重心的有几条路是满足条件的。树上的分治有具体的解析可以去看看理解一下挺简单的,然后差不多树上的分治都可以利用这个模版然后稍微改一下就好。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int M = 1e4 + 10;
    struct Edge {
        int u , v , w , next;
    }edge[M << 1];
    int head[M] , e , Size , n , ans , k;
    bool vis[M];
    void init() {
        memset(head , -1 , sizeof(head));
        memset(vis , false , sizeof(vis));
        ans = e = 0;
    }
    void add(int u , int v , int w) {
        edge[e].v = v;
        edge[e].next = head[u];
        edge[e].w = w;
        head[u] = e++;
    }
    int size[M] , root , mx[M];
    //////
    void dfs_size(int u , int fa)
    {
        size[u] = 1;
        mx[u] = 0;
        for(int i = head[u] ; ~i ; i = edge[i].next) {
            int v = edge[i].v;
            if(v != fa && !vis[v])
            {
                dfs_size(v, u);
                size[u] += size[v];
                if(size[v] > mx[u]) mx[u] = size[v];
            }
        }
    }//找子树包括自生的个数
    void dfs_root(int r, int u, int fa) {
        if(size[r] - size[u] > mx[u]) mx[u] = size[r] - size[u];
        if(mx[u] < Size) Size = mx[u], root = u;
        for(int i = head[u] ; ~i ; i = edge[i].next) {
            int v = edge[i].v;
            if(v != fa && !vis[v]) dfs_root(r, v, u);
        }
    }//找重心
    void get_root(int u , int pre) {
        dfs_size(u , pre);
        dfs_root(u , u , pre);
    }
    //////
    int num = 0 , dis[M];
    void find_dis(int u , int pre , int deep) {
        dis[num++] = deep;
        for(int i = head[u] ; ~i ; i = edge[i].next) {
            int v = edge[i].v;
            if(vis[v] || v == pre) continue;
            find_dis(v , u , deep + edge[i].w);
        }
    }
    int cau(int u , int pre , int deep) {
        num = 0;
        find_dis(u , pre , deep);
        int sum = 0;
        sort(dis , dis + num);
        int l = 0 , r = num - 1;
        while(l < r) {
            while(dis[l] + dis[r] > k && l < r) r--;
            sum += (r - l);
            l++;
        }
        return sum;
    }//这里的cau只要改一下就能解其他类似的点分治问题
    void dfs(int u) {
        Size = n;
        get_root(u , -1);
        vis[root] = true;
        ans += cau(root , -1 , 0);
        int rt = root;
        for(int i = head[root] ; ~i ; i = edge[i].next) {
            int v = edge[i].v;
            if(vis[v]) continue;
            ans -= cau(v , rt , edge[i].w);//这里为什么减去要理解一下然后就没什么问题了
            dfs(v);
        }
    }
    int main() {
        while(~scanf("%d%d" , &n , &k)) {
            if(n == 0 && k == 0) break;
            init();
            for(int i = 0 ; i < n - 1 ; i++) {
                int u , v , l;
                scanf("%d%d%d" , &u , &v , &l);
                add(u , v , l);
                add(v , u , l);
            }
            dfs(1);
            printf("%d
    " , ans);
        }
        return 0;
    }
  • 相关阅读:
    操作系统之磁盘结构笔记
    Linux 操作系统位数(32or64)识别
    手把手教你mysql(十)索引
    Linux命令 — 设置或查看网络配置命令ifconfig
    字符数组的排列
    android 加载图片防止内存溢出
    eCos系统CPU负载测量
    模糊控制——理论基础(4模糊推理)
    模糊控制——理论基础(3模糊关系及其运算)
    模糊控制——理论基础(2隶属函数)
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/7745400.html
Copyright © 2020-2023  润新知