P2325 [SCOI2005]王室联邦 (树上分块)

题意:
给你 1 − n 1-n 1n个城市,然后这个城市是一个树图,求能否将这n个城市划分成至少 B < = s < = 3 B B<=s<=3B B<=s<=3B的一个省,并且这些从这些城市到省会的路径上只能存在本省的城市。

思路:
利用树分块,先将子树的节点划分,如果存在大于B的一块,就划分为树块, u u u为省会,可以证明最后没有被划分的数块树量最大为 B B B,而被划分的树块的最大树量是 2 B − 1 2B-1 2B1

参考代码:

/*
 * @Author: vain
 * @Date: 2020
 * @LastEditTime: 2020-09-17 18:50:03
 * @LastEditors: sueRimn
 * @Description: 学不会 dp 的 fw
 * @FilePath: \main\demo.cpp
 */
//#include <bits/stdc++.h>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
#include <bitset>
using namespace std;
typedef long long ll;
#define ll long long
typedef unsigned long long ull;
const int N = 1e3 + 20;
const ll maxn = 1e5 + 20;
const ll mod = 998244353;
ll head[maxn], stac[maxn], pre[maxn], cnx, cnt;
ll a[maxn], b[maxn], c[maxn], vis[maxn], sizx[maxn];
// typedef pair<ll, ll> p;
// priority_queue<p, vector<p>, greater<p>> m;
//ll sum[maxn];
ll max(ll a, ll b) {
    
     return a > b ? a : b; }
ll min(ll a, ll b) {
    
     return a < b ? a : b; }
ll gcd(ll a, ll b) {
    
     return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) {
    
     return a * b / gcd(a, b); }
void swap(ll &x, ll &y) {
    
     x ^= y, y ^= x, x ^= y; }
map<ull, ll> mp;
//int ik[N], q[N], cnt;
int lowbit(int x) {
    
     return (x) & (-x); }
//vector<ll> f;
ull h[maxn], p[maxn];
const ull base = 13331;
char s[maxn];
ull ksm(ull a, ull b)
{
    
    
    ull res = 1;
    while (b)
    {
    
    
        if (b % 2 == 1)
            res = (a * res);
        b >>= 1ull;
        a = a * a;
    }
    return res - 1;
}
ll ksc(ll x, ll y, ll mod)
{
    
    
    return (x * y - (ll)((long double)x / mod * y) * mod + mod) % mod;
}
ll pos[maxn], snum;
struct node
{
    
    
    ll v, nex;
} e[maxn << 1];
void add(ll u, ll v)
{
    
    
    e[cnx].v = v, e[cnx].nex = head[u];
    head[u] = cnx++;
}
ll n, m;
void dfs(ll u, ll fa)
{
    
    
    //cout << "****" << endl;
    ll cn = snum;
    for (ll i = head[u]; ~i; i = e[i].nex)
    {
    
    
        ll v = e[i].v;
        if (v == fa)
            continue;
        dfs(v, u);
        if (snum - cn >= m)
        {
    
    
            b[++cnt] = u;
            while (snum > cn)
                pos[a[snum--]] = cnt;
        }
    }
    a[++snum] = u;
}
int main()
{
    
    
    // ios::sync_with_stdio(false);
    // cin.tie(0), cout.tie(0);
    // srand(time(NULL));

    scanf("%lld %lld", &n, &m);
    for (ll i = 0; i <= n; i++)
        head[i] = -1;
    for (ll i = 0; i < n - 1; i++)
    {
    
    
        ll u, v;
        scanf("%lld %lld", &u, &v), add(u, v), add(v, u);
    }
    dfs(1, 0);
    if (!cnt)
        pos[1] = ++cnt;
    while (snum)
        pos[a[snum--]] = cnt;
    printf("%lld\n", cnt);
    for (int i = 1; i <= n; i++)
    {
    
    
        printf("%lld%c", pos[i], " \n"[i == n]);
    }
    for (int i = 1; i <= cnt; i++)
    {
    
    
        printf("%lld%c", b[i], " \n"[i == n]);
    }
}

猜你喜欢

转载自blog.csdn.net/yangzijiangac/article/details/108650491