树的重心 图论

朴素

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 5e4 + 10;
vector<int>e[N];
int cnt[N], sum, n, id = 1, ans;
void dfs1(int u, int fa ,int d)
{
    sum += d;
    cnt[u] = 1;
    for (auto it : e[u])
    {
        if (it != fa)
        {
            dfs1(it, u, d + 1);
            cnt[u] += cnt[it];
        }
    }
}
void dfs2(int u, int fa, int sum)
{
    if (sum < ans || (sum == ans && id > u))
    {
        id = u;
        ans = sum;
    }
    for (int it : e[u])
    {
        if (it != fa)
        {
            dfs2(it, u, sum - cnt[it] + n - cnt[it]);
        }
    }
}
int main()
{
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n;
    for (int i = 1; i <= n - 1; i++)
    {
        int x, y;
        cin >> x >> y;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dfs1(1, 0, 0);
    ans = sum;
    dfs2(1, 0, sum);
    cout << id << ' ' << ans;
    return 0;
}

优化 贪心

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 5e4 + 10;
vector<int>e[N];
int cnt[N], sum, n, id = 1, ans;
void dfs1(int u, int fa ,int d)
{
    sum += d;
    cnt[u] = 1;
    for (auto it : e[u])
    {
        if (it != fa)
        {
            dfs1(it, u, d + 1);
            cnt[u] += cnt[it];
        }
    }
}
int main()
{
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n;
    for (int i = 1; i <= n - 1; i++)
    {
        int x, y;
        cin >> x >> y;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dfs1(1, 0, 0);
    ans = sum; id = 1;
    int u = 1, fa = 0;
    while (true)
    {
        bool f = false;
        if (sum < ans || (sum == ans && id > u))
        {
            ans = sum, id = u;
        }
        for (int it : e[u])
        {
                if (it != fa &&cnt[it] * 2 >= n)
                {
                    //取等因为不知道哪个id更小
                    sum = sum-2*cnt[it]+n; f = true;
                    fa = u, u = it; break;
                }
        }
        if (!f)break;
    }
    cout << id << ' ' << ans;
    return 0;
}

带权值 边权 点权

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

const int N = 1e5 + 10;
int n;
ll cnt[N], sum, ans = 0x7fffffffffffffff, wnode[N], w[N * 2], tot;
ll head[N], nxt[N * 2], to[N * 2];
int E = 1;
void add(int x, int y, int val)
{
    to[E] = y;
    nxt[E] = head[x];
    w[E] = val;
    head[x] = E;
    E++;
}
//计算1 计算cnt
void dfs1(int u, int fa, ll d)
{
    sum += d*wnode[u];
    cnt[u] = wnode[u];
    for (int i = head[u]; i != -1; i = nxt[i])
    {
        int t = to[i];
        if (t != fa)
        {
            dfs1(t, u, d + w[i]);
            cnt[u] += cnt[t];
        }
    }
}
void dfs2(int u, int fa, ll s)
{
    if (ans > s)
        ans = s;
    for (int i = head[u]; i != -1; i = nxt[i])
    {
        int t = to[i];
        if (t != fa)
        {
            dfs2(t, u, 1ll*s-cnt[t]*w[i]+(tot-cnt[t])*w[i]);
        }
    }
}
int main()
{
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    memset(head, -1, sizeof(head));
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> wnode[i], tot += wnode[i];
    for (int i = 1; i <= n - 1; i++)
    {
        int x, y, l;
        cin >> x >> y >> l;
        add(x, y, l);
        add(y, x, l);
    }
    dfs1(1, 0, 0);
    ans = sum;
    dfs2(1, 0, sum);
    cout << ans;
    return 0;
}
posted @ 2025-01-23 21:17  闫柏军  阅读(4)  评论(0编辑  收藏  举报