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;
}