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;
}
posted @ 2022-09-01 22:31  传说中的水牛  阅读(107)  评论(0编辑  收藏  举报