• 点分治模板 (洛谷 P3806)


    传送门
    学习了一下点分治。
    点分治基本可以解决树上符合条件的路径的数量的问题。
    流程基本上就是找重心->找不同子树上的路径->找重心。。。

    #include <bits/stdc++.h>
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int MAXN = 1e4 + 10;
    int n, m, q[110], ans[110];
    int head[MAXN], to[MAXN * 2], nxt[MAXN * 2], val[MAXN * 2], tot;
    int maxp[MAXN], siz[MAXN], sum, vis[MAXN], rt, temp[MAXN], cnt;
    bool judge[20000010];
    
    void add(int u, int v, int w){
        to[++tot] = v; val[tot] = w; nxt[tot] = head[u]; head[u] = tot;
    }
    
    void getrt(int u, int fa){
        siz[u] = 1, maxp[u] = 0;
        for(int i = head[u]; i; i = nxt[i]){
            if(fa == to[i] || vis[to[i]]) continue;
            getrt(to[i], u);
            siz[u] += siz[to[i]];
            maxp[u] = max(maxp[u], siz[to[i]]);
        }
        maxp[u] = max(maxp[u], sum - siz[u]);
        if(maxp[u] < maxp[rt]) rt = u;
    }
    
    void getdis(int u, int fa, int dis){
        temp[++cnt] = dis;
        for(int i = head[u]; i; i = nxt[i]){
            if(to[i] == fa || vis[to[i]]) continue;
            getdis(to[i], u, dis + val[i]);
        }
    }
    
    void solve(int u){
        queue<int> que;
        for(int i = head[u]; i; i = nxt[i]){
            if(vis[to[i]]) continue;
            cnt = 0;
            getdis(to[i], u, val[i]);
            for(int k = 1; k <= cnt; k++)
                for(int j = 1; j <= m; j++)
                    if(q[j] >= temp[k]) ans[j] |= judge[q[j] - temp[k]];
            for(int k = 1; k <= cnt; k++) {
                que.push(temp[k]);
                judge[temp[k]] = 1;
            }
        }
        while(!que.empty()) judge[que.front()] = 0, que.pop();
    }
    
    void divide(int u){
        vis[u] = judge[0] = true;
        solve(u);
        for(int i = head[u]; i; i = nxt[i]){
            if(vis[to[i]]) continue;
            maxp[rt = 0] = sum = siz[to[i]];
            getrt(to[i], 0);
            getrt(rt, 0);
            divide(rt);
        }
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("data.in","r",stdin);
        freopen("data.out","w",stdout);
    #endif
        scanf("%d%d", &n, &m);
        for(int i = 1, u, v, w; i < n; i++){
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w);add(v, u, w);
        }
        for(int i = 1; i <= m; i++) scanf("%d", &q[i]);
        maxp[0] = sum = n;
        getrt(1, 0);
        getrt(rt, 0);
        divide(1);
        for(int i = 1; i <= m; i++)
            printf("%s
    ",ans[i] ? "AYE" : "NAY");
        return 0;
    }
    
  • 相关阅读:
    【转】WPF的知识
    【转】WPF绑定模式
    【转】关于easyui的窗口和tab页面不执行js说明
    【转】 jquery easyui Tab 引入页面的问题
    【转】.NET+AE开发中常见几种非托管对象的释放
    【转】C# Graphics类详解
    【转】句柄概念
    storm从入门到放弃(一),storm介绍
    Spark的误解-不仅spark是内存计算,hadoop也是内存计算
    TCP连接中time_wait在开发中的影响-搜人以鱼不如授之以渔
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/12300732.html
Copyright © 2020-2023  润新知