关于点分治的复杂度
  • 板块学术版
  • 楼主happybob
  • 当前回复7
  • 已保存回复7
  • 发布时间2022/7/14 16:36
  • 上次更新2023/10/27 20:22:27
查看原帖
关于点分治的复杂度
332914
happybob楼主2022/7/14 16:36
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <numeric>
#include <cstring>
#include <vector>
using namespace std;

const int N = 2e4 + 5;

int n;
bool st[N];
int p[N][3], k[3];

struct Edge
{
	int v, w;
	Edge(int _v, int _w): v(_v), w(_w){}
};
vector<Edge> G[N];
int dis[N], col[N];

inline int read()
{
	char ch = getchar();
	int x = 0;
	while (ch < '0' || ch > '9') ch = getchar();
	while (ch >= '0' && ch <= '9')
	{
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	return x;
}

int get_wc(int u, int fa, int tot, int& wc)
{
	if (st[u]) return 0;
	int maxn = 0, sum = 0;
	for (int i = 0; i < G[u].size(); i++)
	{
		int j = G[u][i].v;
		if (j == fa) continue;
		int k = get_wc(j, u, tot, wc);
		maxn = max(maxn, k);
		sum += k;
	}
	maxn = max(maxn, tot - sum);
	if (maxn <= tot / 2) wc = u;
	return sum;
}

int get_size(int u, int fa)
{
	if (st[u]) return 0;
	int res = 1;
	for (int i = 0; i < G[u].size(); i++)
	{
		int j = G[u][i].v;
		if (j == fa) continue;
		res += get_size(j, u);
	}
	return res;
}

int wp[3];

void get_dist(int u, int fa, int& c, int color, int w)
{
	if (st[u]) return;
	dis[++c] = w;
	p[color][w % 3]++;
	k[w % 3]++;
	col[c] = color;
	for (int i = 0; i < G[u].size(); i++)
	{
		int j = G[u][i].v;
		if (j == fa) continue;
		get_dist(j, u, c, color, w + G[u][i].w);
	}
}

int calc(int u)
{
	if (st[u]) return 0;
	k[0] = k[1] = k[2] = 0;
	int res = 0;
	get_wc(u, -1, get_size(u, -1), u);
	st[u] = true;
	int cur = 0;
	for (int i = 0; i < G[u].size(); i++)
	{
		//wp[0] = wp[1] = wp[2] = 0;
		get_dist(G[u][i].v, u, cur, i, G[u][i].w);
		//bt[0].add(i + 1, wp[0], G[u].size());
		//bt[1].add(i + 1, wp[1], G[u].size());
		//bt[2].add(i + 1, wp[2], G[u].size());
	}
	for (int i = 1; i <= cur; i++)
	{
		res += (dis[i] % 3 == 0) << 1;
		int cg = 3 - dis[i] % 3;
        cg = cg % 3;
		res += (k[cg] - p[col[i]][cg]);
	}
    for (int i = 0; i < G[u].size(); i++)
	{
		p[i][0] = p[i][1] = p[i][2] = 0;
	}
	for (int i = 0; i < G[u].size(); i++) res += calc(G[u][i].v);
	return res;
}

signed main()
{
	n = read();
	for (int i = 1; i < n; i++)
	{
		int u = read(), v = read(), w = read();
		G[u].push_back(Edge(v, w));
		G[v].push_back(Edge(u, w));
	}
	int total = n * n, p = calc(1) + n, g = __gcd(total, p);
	printf("%d/%d\n", p / g, total / g);
	return 0;
}

这份代码在P2634上最后两个点T了,现在看来不是常数问题,应该是代码复杂度假了,但不知道问题在哪。能帮忙看看吗?

2022/7/14 16:36
加载中...