求助,WA #10
查看原帖
求助,WA #10
1241526
zhangzhenxuan812楼主2024/9/5 16:16

Kruskal + lca算法求的,看题解里很多也是这个算法,但我的#10输出比标准答案小,且大于最小生成树的边权和,是答案不够严谨,还是求的时候细节问题?其他点都AC了,码在下面,数组d1是路径上最大边权,d2是路径上严格次大边权

#include<bits/stdc++.h>
using namespace std;

struct pic
{
	long long a, b, c;
} edge[300010];

long long read()
{
	long long mid = 0;
	char c = getchar();
	while(c < '0' or c > '9') c = getchar();
	while(c >= '0' and c <= '9')
	{
		mid = mid * 10 + (c - '0');
		c = getchar();
	}
	return mid;
}

long long h[100010], e[600010], ne[600010], idx = 1;
long long w[600010];

void add(long long a, long long b, long long c)
{
	e[idx] = h[a];
	ne[idx] = b;
	w[idx] = c;
	h[a] = idx++;
	return;
}

long long n, m;
long long min_sum = 0, ans = 1e18;
long long father[100010];

bool cmp(pic a, pic b)
{
	return a.c < b.c;
}

long long _find(long long x)
{
	if(father[x] == x) return father[x];
	father[x] = _find(father[x]);
	return father[x];
}

long long f[100010][21], dep[100010];
long long d1[100010][21], d2[100010][21];
bool vis[100010];

void dfs(long long u)
{
	for(long long i = h[u]; i != -1; i = e[i])
	{
		long long j = ne[i];
		if(vis[j]) continue;
		vis[j] = 1;
		dep[j] = dep[u] + 1;
		f[j][0] = u;
		d1[j][0] = w[i];
		for(long long k = 1; k < 20; k++)
		{
			long long a = d1[j][k - 1];
			long long b =  d1[f[j][k - 1]][k - 1];
			f[j][k] = f[f[j][k - 1]][k - 1];
			d1[j][k] = max(a, b);
			if(a == b) d2[j][k] = max(d2[j][k - 1], d2[f[j][k - 1]][k - 1]);
			else if(a > b) d2[j][k] = max(d2[j][k - 1], b);
			else if(a < b) d2[j][k] = max(a, d2[f[j][k - 1]][k - 1]);
		}
		dfs(j);
	}
	return;
}

long long lca(long long x, long long y, long long v)
{
	long long a = -1, b = -1;
	if(dep[x] < dep[y]) swap(x, y);
	for(long long k = 19; k >= 0; k--)
	{
		if(dep[f[x][k]] >= dep[y])
		{
			if(d1[x][k] > a)
			{
				b = max(max(a, b), d2[x][k]);
				a = max(d1[x][k], a);
			}
			if(d1[x][k] == a) b = max(b, d2[x][k]);
			if(d1[x][k] < a) b = max(b, d1[x][k]);
			x = f[x][k];
		}
	}
	if(x == y)
	{
		if(b == -1) return (v - a);
		if(v > a) return (v - a);
		else return (v - b);
	}
	for(long long k = 19; k >= 0; k--)
	{
		if(f[x][k] != f[y][k])
		{
			if(d1[x][k] > a)
			{
				b = max(max(a, b), d2[x][k]);
				a = max(d1[x][k], a);
			}
			if(d1[x][k] == a) b = max(b, d2[x][k]);
			if(d1[x][k] < a) b = max(b, d1[x][k]);
			if(d1[y][k] > a)
			{
				b = max(max(a, b), d2[y][k]);
				a = max(d1[y][k], a);
			}
			if(d1[y][k] == a) b = max(b, d2[y][k]);
			if(d1[y][k] < a) b = max(b, d1[y][k]);
			x = f[x][k];
			y = f[y][k];
		}
	}
	if(d1[x][0] > a)
	{
		b = max(max(a, b), d2[x][0]);
		a = max(d1[x][0], a);
	}
	if(d1[x][0] == a) b = max(b, d2[x][0]);
	if(d1[x][0] < a) b = max(b, d1[x][0]);
	if(d1[y][0] > a)
	{
		b = max(max(a, b), d2[y][0]);
		a = max(d1[y][0], a);
	}
	if(d1[y][0] == a) b = max(b, d2[y][0]);
	if(d1[y][0] < a) b = max(b, d1[y][0]);
	if(b == -1) return (v - a);
	if(v > a) return (v - a);
	else return (v - b);
}

int main()
{
	memset(h, -1, sizeof(h));
	memset(d1, -1, sizeof(d1));
	memset(d2, -1, sizeof(d2));
	n = read(); m = read();
	for(long long i = 1; i <= n; i++) father[i] = i;
	for(long long i = 1; i <= m; i++)
	{
		edge[i].a = read();
		edge[i].b = read();
		edge[i].c = read();
	}
	sort(edge + 1, edge + 1 + m, cmp);
	for(long long i = 1; i <= m; i++)
	{
		long long id_a = _find(edge[i].a), id_b = _find(edge[i].b);
		if(id_a == id_b) continue;
		father[id_a] = id_b;
		add(edge[i].a, edge[i].b, edge[i].c);
		add(edge[i].b, edge[i].a, edge[i].c);
		min_sum += edge[i].c;
	}
	dep[1] = 1;
	dfs(1);
	for(long long i = 1; i <= m; i++)
	{
		long long a = edge[i].a, b = edge[i].b, c = edge[i].c;
		if(a == b) continue;
		long long mid = lca(a, b, c);
		if(mid <= 0) continue;
		ans = min(ans, min_sum + mid);
	}
	cout << ans;
	return 0;
}


2024/9/5 16:16
加载中...