BZOJ2097 [Usaco2010 12月]運動牛エアロビクス貪欲

トピックポータル

https://lydsy.com/JudgeOnline/problem.php?id=2097

問題の解決策

明らかにバイナリ\(MID \)は、各ブロックの長さの最大直径を表し、通信の数が最小ブロック要求を必要とします。

その後、我々は場合に見出さ正当頂点通信ブロックせずに通信ブロックの直径いずれの場合にも、元の直径の長辺を作ることができないので、次に頂点ときプラス側に、通信ブロックの直径は、無視することができます。それで最長の連鎖の頂点から下方に考慮することが必要なだけです。

だから我々は、録音([I] \ F)\をで表さ\(私は\) 最長ルートブロック通信の鎖長です。すべてその後、我々はルートに木からサブマージされ、貪欲されます([息子] F \)\がソートされ、その後、最大の満足を見つける隣接する二つの少ないマージ\(中旬\)があります。後者は、すべてのカットオフが必要となります。


ソートする必要が、時間の複雑さのために以下のコードを、\(O(N \ N-ログ)\)

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back

template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}

typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;

template<typename I>
inline void read(I &x) {
    int f = 0, c;
    while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    x = c & 15;
    while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    f ? x = -x : 0;
}

const int N = 1e5 + 7;

int n, m, cnt;
int tt[N], f[N];

struct Edge { int to, ne; } g[N << 1]; int head[N], tot;
inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y) { addedge(x, y), addedge(y, x); }

inline void dfs(int x, const int &mid, int fa = 0) {
    for fec(i, x, y) if (y != fa) dfs(y, mid, x);
    tt[0] = 0, f[x] = 0;
    for fec(i, x, y) if (y != fa) tt[++tt[0]] = f[y] + 1;
    std::sort(tt + 1, tt + tt[0] + 1);
    for (int i = tt[0]; i; --i)
        if ((i == 1 && tt[i] <= mid) || tt[i] + tt[i - 1] <= mid) {
            f[x] = tt[i];
            break;
        } else ++cnt;
}

inline bool check(const int &mid) {
    cnt = 0;
    dfs(1, mid);
    return cnt <= m;
}

inline void work() {
    int l = 0, r = n - 1;
    while (l < r) {
        int mid = (l + r) >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    printf("%d\n", l);
}

inline void init() {
    read(n), read(m);
    for (int i = 1; i < n; ++i) {
        int x, y;
        read(x), read(y);
        adde(x, y);
    }
}

int main() {
#ifdef hzhkk
    freopen("hkk.in", "r", stdin);
#endif
    init();
    work();
    fclose(stdin), fclose(stdout);
    return 0;
}

おすすめ

転載: www.cnblogs.com/hankeke/p/BZOJ2097.html