求 hack 思路
查看原帖
求 hack 思路
481621
Zhang_Wenjie楼主2024/7/10 13:10

我的思路是:找到任意直径 p -> q 长度为 d,

然后 从 p dfs 一遍标记所有直径的另一端 qi(正确性是显然的,所有直径的两端都是相齐的)

对 qi 找多点 lca,就是 q 端的必经点 lcaq

对称过来找到 p 端 的必经点 lcap

必经边的长度就是 dep[lcap] + dep[lcaq] - 2 * dep[lca(lcap, lcaq)]

样例过了,但只有 20pts

附:

#include <bits/stdc++.h>
#define re register int 

using namespace std;
typedef long long LL;
const int N = 2e5 + 10, logN = 50;
const int inf = 0x3f3f3f3f;

struct Edge
{
	int to, w, next;
}e[N << 1];
int top, h[N];
int f[N][logN], dep[N], sum[N];
int n, p, q, dfn[N], idx;
LL len, maxs;
bool st[N];

inline void add(int x, int y, int w)
{
	e[++ top] = (Edge){y, w, h[x]};
	h[x] = top;
}

void dfs(int u, int fa, LL size, int & ver, int type)
{
	if (size > maxs)
	{
		maxs = size;
		ver = u;
		
		if (type) len = size;
	}
	for (re i = h[u]; i; i = e[i].next)
	{
		int v = e[i].to, w = e[i].w;
		
		if (v == fa) continue;
		dfs(v, u, size + w, ver, type);
	}
}

void draw(int u, int fa, LL size)
{
	if (size == len)
	{
		st[u] = true;
		return;
	}
	
	for (re i = h[u]; i; i = e[i].next)
	{
		int v = e[i].to, w = e[i].w;
		
		if (v == fa) continue;
		draw(v, u, size + w);
	}
}

void init(int u, int fa)
{
	dep[u] = dep[fa] + 1;
	f[u][0] = fa;
	
	for (re i = 1; i <= log2(n); i ++)
		f[u][i] = f[f[u][i - 1]][i - 1];
		
	for (re i = h[u]; i; i = e[i].next)
	{
		int v = e[i].to, w = e[i].to;
		
		if (v == fa) continue;
		
		sum[v] = sum[u] + w;
		init(v, u);
	}
}

inline int lca(int u, int v)
{
	if (dep[u] < dep[v]) swap(u, v);
	
	for (re i = log2(n); i >= 0; i --)
		if (dep[f[u][i]] >= dep[v]) u = f[u][i];
	if (u == v) return u;
	
	for (re i = log2(n); i >= 0; i --)
		if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
	return f[u][0];
}

void get_dfn(int u, int fa)
{
	dfn[++ idx] = u;
	
	for (re i = h[u]; i; i = e[i].next)
	{
		int v = e[i].to;
		if (v == fa) continue;
		get_dfn(v, u);
	}
	
	dfn[++ idx] = u;
}

inline void work()
{	
	draw(p, 0, 0); 
	init(1, 0);
	get_dfn(1, 0);
	
//	cout << p << ' ' << q << '\n';
//	for (re i = 1; i <= n; i ++) cout << i << ' ' << st[i] << '\n';
//	for (re i = 1; i <= idx; i ++)
//		cout << dfn[i] << ' ';
	
	int minn = inf, maxn = 0, l, r;
	for (re i = 1; i <= idx; i ++)
		if (st[dfn[i]])
		{
			if (i < minn) minn = i, l = dfn[i];
			if (i > maxn) maxn = i, r = dfn[i];
		}	
//	cout << '\n' << l << ' ' << r << '\n';
	int lcap = lca(l, r);
	
//	cout << lcap << '\n';
	
	memset(dep, 0, sizeof(dep));
	memset(f, 0, sizeof(f));
	memset(sum, 0, sizeof(sum));
	memset(st, false, sizeof(st));
	minn = inf, maxn = 0;
	idx = 0;
	
	draw(q, 0, 0);
	init(1, 0);
	get_dfn(1, 0);
	
	for (re i = 1; i <= idx; i ++)
		if (st[dfn[i]])
		{
			if (i < minn) minn = i, l = dfn[i];
			if (i > maxn) maxn = i, r = dfn[i];
		}	
	int lcaq = lca(l, r);
	
//	cout << lcaq << '\n';

	cout << dep[lcap] + dep[lcaq] - 2 * dep[lca(lcap, lcaq)] << '\n';
	
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n;
	for (re i = 1; i < n; i ++)
	{
		int x, y, w; cin >> x >> y >> w;
		add(x, y, w);
		add(y, x, w);
	}
	
	dfs(1, 0, 0, p, 0);
	maxs = 0;
	dfs(p, 0, 0, q, 1);	
	
	cout << len << '\n';
	work();
	
	return 0;
}
2024/7/10 13:10
加载中...