Kruscal 加 树剖,线段树内存第一,二大的值,小常数但是 T 飞了,求调
但我还是要为树剖代言, T 了全是个人太菜,和树剖无关,资瓷树剖。
AC #1,2,3,4,5, subtask #1,2, T 6,7,8,9,10
#include<bits/stdc++.h>
#define int long long
#define reg register
#define N 300100
const int INF = 0x7ffffffff;
using namespace std;
//char in[1 << 20] ,*ss = in,*tt = in;
//#define getchar() (tt == ss && (tt = (ss = in) + fread(in, 1, 1 << 20,stdin),ss == tt) ? EOF : *ss++)
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch > '9' || ch < '0')
{
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int n, m;
int ans, p[N], mixn = INF;
struct Link
{
int a, b, w;
bool st;
}link[N];
bool Sort(Link x, Link y) { return x.w < y.w; }
struct edges
{
int nxt, ver, val;
#define nxt(p) edge[p].nxt
#define ver(p) edge[p].ver
#define val(p) edge[p].val
}edge[N << 1];
int head[N], tot;
inline void add(int a, int b, int c)
{
edge[++ tot].nxt = head[a];
edge[tot].val = c;
edge[tot].ver = b;
head[a] = tot;
}
int fa[N], sze[N];
int find(int x) { return fa[x] == x ? x : find(fa[x]); }
void merge(int x, int y)
{
int fx = find(x), fy = find(y);
if(sze[fx] < sze[fy]) swap(fx, fy);
fa[fy] = fx;
sze[fx] += sze[fy];
}
int son[N], dep[N];
void get_son(int x, int Fa)
{
fa[x] = Fa;
dep[x] = dep[Fa] + 1;
sze[x] = 1;
for(reg int i = head[x];i ; i = nxt(i))
{
int y = ver(i);
if(y == Fa) continue;
get_son(y, x);
int w = val(i);
p[y] = w;
sze[x] += sze[y];
sze[son[x]] < sze[y] ? son[x] = y : y = y;
}
}
int dfn[N], vlu[N], cnt, top[N];
void get_chain(int x, int Top)
{
dfn[x] = ++ cnt;
vlu[cnt] = p[x];
top[x] = Top;
if(!son[x]) return;
get_chain(son[x], Top);
for(reg int i = head[x];i ;i = nxt(i))
{
int y = ver(i);
if(y == fa[x] || y == son[x]) continue;
get_chain(y, y);
}
}
struct Sgtree
{
int l, r, fir, sec;
#define l(p) tree[p].l
#define r(p) tree[p].r
#define fir(p) tree[p].fir
#define sec(p) tree[p].sec
}tree[N << 2];
void build(int p, int l, int r)
{
l(p) = l, r(p) = r;
if(l == r)
{
fir(p) = vlu[l];
sec(p) = -INF;
return;
}
int mid = l + r >> 1;
build(p << 1, l , mid);
build(p << 1 | 1, mid + 1, r);
fir(p) = max(fir(p << 1), fir(p << 1 | 1));
if(fir(p << 1) == fir(p << 1 | 1)) sec(p) = max(sec(p << 1), sec(p << 1 | 1));
else sec(p) = max( max(sec(p << 1), sec(p << 1 | 1)), min(fir(p << 1), fir(p << 1 | 1)) );
}
// 1 -> fir 0 -> sec
int qry(int p, int l, int r, bool op)
{
if(l(p) >= l && r(p) <= r) return (op ? fir(p) : sec(p));
int mid = l(p) + r(p) >> 1;
int Fir = -INF, Sec = -INF;
if(l <= mid)
{
int lsf = qry(p << 1, l, r, 1);
int lsc = qry(p << 1, l, r, 0);
Fir = lsf, Sec = lsc;
}
if(r > mid)
{
int rsf = qry(p << 1 | 1, l, r, 1);
int rsc = qry(p << 1 | 1, l, r, 0);
if(Fir == -INF) Fir = rsf, Sec = rsc;
else
{
if(Fir == rsf) Sec = max(Sec, rsc);
else Sec = max( max(Sec, rsc) , min(Fir, rsf) );
Fir = max(Fir, rsf);
}
}
return (op ? Fir : Sec);
}
int ch_qry(int x, int y, int op)
{
int Fir = -INF, Sec = -INF;
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x, y);
int pf = qry(1, dfn[top[x]], dfn[x], 1);
int pc = qry(1, dfn[top[x]], dfn[x], 0);
if(Fir == -INF) Fir = pf, Sec = pc;
else
{
if(Fir == pf) Sec = max(Sec, pc);
else Sec = max( max(Sec, pc), min(pf, Fir) );
Fir = max(Fir, pf);
}
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
int pf = qry(1, dfn[x] + 1, dfn[y], 1);
int pc = qry(1, dfn[x] + 1, dfn[y], 0);
if(Fir == -INF) Fir = pf, Sec = pc;
else
{
if(Fir == pf) Sec = max(Sec, pc);
else Sec = max( max(Sec, pc), min(pf, Fir) );
Fir = max(Fir, pf);
}
return (op ? Fir : Sec);
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n = read(), m = read();
for(reg int i = 1;i <= m;i = -~i) link[i] = {read(), read(), read(), 0};
sort(link + 1, link + m + 1, Sort);
for(reg int i = 1;i <= n;i = -~i) fa[i] = i, sze[i] = 1;
for(reg int i = 1;i <= m;i = -~i)
{
int x = link[i].a, y = link[i].b, w = link[i].w;
int fx = find(x), fy = find(y);
if(fx == fy) continue;
ans += w;
link[i].st = 1;
add(x, y, w);
add(y, x, w);
merge(fx, fy);
}
// ------------------------ Kruscal
memset(fa, 0, sizeof fa);
memset(sze, 0, sizeof sze);
get_son(1 , 1);
get_chain(1, 1);
build(1, 1, n);
for(reg int i = 1;i <= m;i = -~i)
{
if(link[i].st) continue;
int x = link[i].a, y = link[i].b, z = link[i].w;
int Fir = ch_qry(x, y, 1);
int Sec = ch_qry(x, y, 0);
if(z != Fir) mixn = min(mixn, z - Fir);
else mixn = min(mixn, z - Sec);
}
printf("%lld", ans + mixn);// mixn 存的是比原 ans 大多少
return 0;
}