ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P4149 距离为K的点对(最少边数) n=200000 点分治

2019-03-06 13:52:00  阅读:244  来源: 互联网

标签:200000 sz fa int deep dep num P4149 边数


这题数据范围变成了200000 n^2就过不了 同时要求求的是最少的边数 不能容斥

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5;
const int MAXM = 2e5 + 5;
int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], ed = 1;
int cost[MAXM << 1];
int ok[1000005];
inline void addedge(int u, int v, int c) {
        to[++ed] = v;
        cost[ed] = c;
        nxt[ed] = Head[u];
        Head[u] = ed;
}
inline void ADD(int u, int v, int c) {
        addedge(u, v, c);
        addedge(v, u, c);
}
int n, anser, k, cnt;
int sz[MAXN], f[MAXN], dep[MAXN], sumsz, root;
bool vis[MAXN];
pair<int, int> o[MAXN];
int num[MAXN];
void getroot(int x, int fa) {
        sz[x] = 1;
        f[x] = 0;
        for (int i = Head[x]; i; i = nxt[i]) {
                int v = to[i];
                if (v == fa || vis[v]) {
                        continue;
                }
                getroot(v, x);
                sz[x] += sz[v];
                f[x] = max(f[x], sz[v]);
        }
        f[x] = max(f[x], sumsz - sz[x]);
        if (f[x] < f[root]) {
                root = x;
        }
}
void getdeep(int x, int fa, int deep) {
        if (dep[x] > k) {
                return;
        }
        o[++cnt] = make_pair(dep[x], deep);
        num[++num[0]] = dep[x];
        for (int i = Head[x]; i; i = nxt[i]) {
                int v = to[i];
                if (v == fa || vis[v]) {
                        continue;
                }
                dep[v] = dep[x] + cost[i];
                getdeep(v, x, deep + 1);
        }
}
void calc(int x, int d) {
        num[0] = 0;
        dep[x] = d;
        for (int i = Head[x]; i; i = nxt[i]) {
                int v = to[i];
                if (vis[v]) {
                        continue;
                }
                cnt = 0;
                dep[v] = dep[x] + cost[i];
                getdeep(v, x, 1);
                for (int j = 1; j <= cnt; j++) {
                        if (o[j].first <= k) {
                                if (ok[k - o[j].first] != INT_MAX) {
                                        anser = min(anser, ok[k - o[j].first] + o[j].second);
                                }
                        }
                }
                for (int j = 1; j <= cnt; j++) {
                        if (o[j].first <= k) {
                                ok[o[j].first] = min(o[j].second, ok[o[j].first]);
                        }
                }
        }
        for (int i = 1; i <= num[0]; i++) {
                ok[num[i]] = INT_MAX;
        }
}
void solve(int x) {
        vis[x] = 1;
        calc(x, 0);
        for (int i = Head[x]; i; i = nxt[i]) {
                int v = to[i];
                if (vis[v]) {
                        continue;
                }
                root = 0, sumsz = sz[v];
                getroot(v, 0);
                solve(root);
        }
}
int main() {
        scanf("%d %d", &n, &k);
        anser = INT_MAX;
        for (int i = 1; i <= k; i++) {
                ok[i] = INT_MAX;
        }
        cnt = 0;
        memset(Head, 0, sizeof(Head));
        memset(vis, 0, sizeof(vis));
        ed = 1;
        int u, v, c;
        for (int i = 1; i < n; i++) {
                scanf("%d %d %d", &u, &v, &c);
                ADD(u + 1, v + 1, c);
        }
        root = 0, sumsz = f[0] = n;
        getroot(1, 0);
        solve(root);
        printf("%d\n", anser == INT_MAX ? -1 : anser);
        return 0;
}
View Code

注意dep[x]>k的时候要return 不然会re

标签:200000,sz,fa,int,deep,dep,num,P4149,边数
来源: https://www.cnblogs.com/Aragaki/p/10482758.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有