树的重心 图论
朴素
#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;
}