p1364 带权树找重心
在洛谷上,写题解还有数量限制?
本来就只是想做个记录,没想到还不让提交。
所以在这里写了。
思路如图:
AC代码如下
namespace Buffalo{
struct HeadNxtG{
vector<int> head;
vector<int> ver;
vector<int> nxt;
vector<int> nodeWi;
int tot;
HeadNxtG(int nodeLen,int edgeLen){
head.resize(nodeLen);
nodeWi.resize(nodeLen);
ver.resize(edgeLen<<1);
nxt.resize(edgeLen<<1);
tot=0;
}
void add(int u,int v){
ver[++tot] = v;
nxt[tot] = head[u];
head[u] = tot;
}
void addE(int u,int v){
add(u,v);
add(v,u);
}
};
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int N;
cin >> N;
int w, l, r;
Buffalo::HeadNxtG hng(N + 1, N + 1);
for (int i = 1; i <= N; ++i) {
cin >> w >> l >> r;
hng.nodeWi[i] = w;
if(l>0)hng.addE(i, l);
if(r>0)hng.addE(i, r);
}
vector<int> num(N + 1);
vector<int> dp(N + 1);
function<void(int, int,int)> dfs = [&](int u, int fa,int depth) {
num[u] = hng.nodeWi[u];
for (int e = hng.head[u]; e > 0; e = hng.nxt[e]) {
int v = hng.ver[e];
if (v != fa) {
dfs(v, u,depth+1);
num[u] += num[v];
}
}
dp[1] += hng.nodeWi[u] * depth;
};
int ret = INT_MAX;
function<void(int, int)> calcdp = [&](int u, int fa) {
for (int e = hng.head[u]; e > 0; e = hng.nxt[e]) {
int v = hng.ver[e];
if (v != fa) {
dp[v] = dp[u] + num[1] - num[v] * 2;
calcdp(v, u);
}
}
ret = min(ret, dp[u]);
};
dfs(1, 0, 0);
calcdp(1, 0);
cout << ret << endl;
return 0;
}
如果是不带权的树查找重心,那么就只需要一次dfs即可。
思路如下。
在 dfs中,对于每个子树:
nodeCnt[u] += nodeCnt[v];
weight[u] = max(weight[u], nodeCnt[v]);
然后:
weight[u] = max(weight[u], N-nodeCnt[u]);
如果 weight[u] <= 2 那么u 有可能是重心。
附poj 1655的AC代码
#include <iostream>
#include <cassert>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <cmath>
#include <climits>
#include <functional>
#include <list>
#include <cstdlib>
#include <set>
#include <stack>
#include <map>
#include <algorithm>
#include <bitset>
#define endl "\n"
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
using namespace std;
#define NMAX 20005
int head[NMAX];
int ver[NMAX<<1];
int nxt[NMAX<<1];
int tot;
int wi[NMAX];
int nodeCnt[NMAX];
int N;
int ret;
int pos;
void Init(){
memset(head, 0, sizeof(head));
memset(ver, 0, sizeof(ver));
memset(nxt, 0, sizeof(nxt));
memset(wi, 0, sizeof(wi));
memset(nodeCnt, 0, sizeof(nodeCnt));
tot = 0;
ret = N / 2 + 1;
}
void addH(int u, int v) {
ver[++tot] = v;
nxt[tot] = head[u];
head[u] = tot;
}
void add(int u, int v) {
addH(u, v);
addH(v, u);
}
void dfs(int u, int fa) {
wi[u] = 0;
nodeCnt[u] = 1;
for (int e = head[u]; e; e = nxt[e]) {
int v = ver[e];
if (v != fa) {
dfs(v,u);
nodeCnt[u] += nodeCnt[v];
wi[u] = max(wi[u], nodeCnt[v]);
}
}
wi[u] = max(wi[u], N - nodeCnt[u]);
if (ret > wi[u]) {
pos = u;
ret = wi[u];
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
int u, v;
while (t-- > 0) {
cin >> N;
Init();
for (int i = 1; i < N; ++i) {
cin >> u >> v;
add(u, v);
}
dfs(1, 0);
cout << pos << " " << ret << endl;
}
return 0;
}