这是一道水题。。。。
题目要求的一幅图的严格次小生成树(就是说权值和要大于最小生成树,不能等于)
我们先来分析一下:
假设我们现在得到了最小生成树。
我们可以发现次小生成树肯定只是最小生成树修改一条边而已。。。这个很显然。
然后我们枚举非树边。
加入这条边之后我们会出现一个环(然后环切。)
我们要求两个东西,这个环(除了加进去的那条边之外)的最大权值和次大权值(严格意义)
可以发现的是,最大权值必定<=当前边的权值。
假如等于的话,我们就取代次大权值的边,否则,取代最大权值的边。
最后再更新一下答案就好了。
#include
#include
#include
using namespace std;
const int MAXN = 500005;
struct Node
{
int son[2],fa,max,cmax;bool rev;
}T[MAXN];
struct Edge
{
int u,v,cost;
}E[MAXN];
int Par[MAXN],Fa[MAXN],V[MAXN],N,M;
bool bz[MAXN];
pair
H;
bool cmp(Edge a,Edge b) {return a.cost < b.cost;}
int get(int a) {return Fa[a] == a ? a : Fa[a] = get(Fa[a]);}
void Upd(int Nt,int l)
{
if (T[l].max > T[Nt].max) T[Nt].cmax = max(T[Nt].max,T[l].cmax),T[Nt].max = T[l].max; else
if (T[l].max < T[Nt].max) T[Nt].cmax = max(T[Nt].cmax,T[l].max);
}
void Update(int Nt)
{
T[Nt].max = V[Nt],T[Nt].cmax = 0;
int l = T[Nt].son[0],r = T[Nt].son[1];
Upd(Nt,l),Upd(Nt,r);
}
void Label(int u)
{
T[u].rev ^= 1,swap(T[u].son[0],T[u].son[1]);
}
void Lazy_down(int u)
{
if (T[u].rev) Label(T[u].son[0]),Label(T[u].son[1]),T[u].rev = 0;
}
void Rotate(int u,int c)
{
int fa = T[u].fa,ft = T[fa].fa;
Lazy_down(u);
T[fa].fa = u,T[u].fa = ft;
if (ft) T[ft].son[T[ft].son[1] == fa] = u;
T[fa].son[c] = T[u].son[!c];
if (T[u].son[!c]) T[T[u].son[!c]].fa = fa;
T[u].son[!c] = fa;
Update(fa);
if (Par[fa]) Par[u] = Par[fa],Par[fa] = 0;
}
void Splay(int u)
{
for(Lazy_down(u);T[u].fa;)
{
int fa = T[u].fa,ft = T[fa].fa;
Lazy_down(ft),Lazy_down(fa);
if (!ft) Rotate(u,T[fa].son[1] == u); else
{
if (T[fa].son[1] == u)
{
if (T[ft].son[1] == fa) Rotate(fa,1),Rotate(u,1); else
Rotate(u,1),Rotate(u,0);
} else
if (T[ft].son[0] == fa) Rotate(fa,0),Rotate(u,0); else
Rotate(u,0),Rotate(u,1);
}
}
Update(u);
}
int Access(int u,bool h)
{
int nxt = 0;
while (u)
{
Splay(u);
if (h && !Par[u])
{
H = make_pair(T[nxt].max,T[nxt].cmax);
int x = T[u].son[1];
if (T[x].max > H.first) H.second = max(T[x].cmax,H.first),H.first = T[x].max; else
if (T[x].max < H.first) H.second = max(H.second,T[x].max);
}
if (T[u].son[1]) T[T[u].son[1]].fa = 0,Par[T[u].son[1]] = u;
T[u].son[1] = nxt;if (nxt) T[nxt].fa = u;Par[nxt] = 0;
Update(u);
nxt = u,u = Par[u];
}
return nxt;
}
void Evert(int u)
{
Label(Access(u,0));
}
void link(int u,int v)
{
Evert(u),Evert(v),Splay(v),Par[v] = u,Access(v,0);
}
int main()
{
scanf("%d %d", &N, &M);
for(int i = 1;i <= M;i ++) scanf("%d %d %d", &E[i].u, &E[i].v, &E[i].cost);
for(int i = 1;i <= N;i ++) Fa[i] = i;
sort(E + 1,E + M + 1,cmp);
long long Total = 0;
for(int i = 1;i <= M;i ++)
if (get(E[i].u) != get(E[i].v))
{
Fa[get(E[i].u)] = get(E[i].v);
bz[i] = 1;
Total += E[i].cost;
V[i + N] = E[i].cost,link(E[i].u,i + N),link(i + N,E[i].v);
}
long long Ans = 1LL << 61;
for(int i = 1;i <= M;i ++) if (!bz[i])
{
Access(E[i].u,0),Access(E[i].v,1);
if (H.first == E[i].cost) Ans = min(Ans,(long long)E[i].cost - H.second); else
if (H.first != E[i].cost) Ans = min(Ans,(long long)E[i].cost - H.first);
}
printf("%I64d\n",Total + Ans);
}