参考题目:洛谷P3366
解析:
联赛完后统一更模板题解析。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline
int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
cs int N=5005,M=200005;
int w[N+M],from[N+M],to[N+M];
typedef struct splay_node *point;
struct splay_node{
point son[2],fa;
int val,pos,ori;
bool tag;
splay_node(){
son[0]=son[1]=fa=NULL;
tag=val=pos=0;
}
point &lc(){return son[0];}
point &rc(){return son[1];}
bool isroot(){return !fa||(fa->son[0]!=this&&fa->son[1]!=this);}
bool which(){return this==fa->son[1];}
void init(){
son[0]=son[1]=fa=NULL;
tag=val=pos=0;
}
void pushdown(){
if(tag){
swap(son[0],son[1]);
if(son[0])son[0]->tag^=1;
if(son[1])son[1]->tag^=1;
tag=0;
}
}
void pushup(){
pos=ori,val=w[ori];
if(son[0]&&son[0]->val>val){
pos=son[0]->pos;
val=son[0]->val;
}
if(son[1]&&son[1]->val>val){
pos=son[1]->pos;
val=son[1]->val;
}
}
}ttt[N+M];
struct Link_Cut_Tree{
point tr[N+M];
Link_Cut_Tree(int n=N+M-1){for(int re i=0;i<=n;++i)tr[i]=&ttt[i],ttt[i].ori=i;}
void Rotate(point now){
point Fa=now->fa,FA=Fa->fa;
bool pos=now->which();
if(FA&&!Fa->isroot())FA->son[Fa->which()]=now;
Fa->fa=now;
now->fa=FA;
Fa->son[pos]=now->son[!pos];
if(Fa->son[pos])Fa->son[pos]->fa=Fa;
now->son[!pos]=Fa;
Fa->pushup();
now->pushup();
}
void Splay(point now){
static point q[N+M];
static int qn;
q[qn=1]=now;
for(point Fa=now;!Fa->isroot();Fa=Fa->fa)q[++qn]=Fa->fa;
for(int re i=qn;i;--i)q[i]->pushdown();
for(point Fa=now->fa;!now->isroot();Rotate(now),Fa=now->fa)
if(!Fa->isroot())Rotate(now->which()==Fa->which()?Fa:now);
}
void access(point now){
for(point son=NULL;now;son=now,now=now->fa)
Splay(now),now->rc()=son,now->pushup();
}
void makeroot(point now){
access(now);Splay(now);now->tag^=1;
}
point findroot(point now){
access(now),Splay(now);
while(now->lc())now=now->lc();
return now;
}
bool connect(point u,point v){
makeroot(u);
return findroot(v)==u;
}
bool connect(int u,int v){return connect(tr[u],tr[v]);}
void link(point u,point v){
makeroot(u),u->fa=v;
}
void link(int u,int v){link(tr[u],tr[v]);}
void cut(point u,point v){
makeroot(u),access(v),Splay(v);
v->lc()=u->fa=NULL;
}
void cut(int u,int v){cut(tr[u],tr[v]);}
int query(point u,point v){
makeroot(u);
access(v);
Splay(v);
return v->pos;
}
int query(int u,int v){return query(tr[u],tr[v]);}
}LCT;
int n,m,ecnt;
int ans,tot;
signed main(){
ecnt=n=getint();
m=getint();
for(ecnt=n+1;ecnt<=n+m;++ecnt){
int u=from[ecnt]=getint(),v=to[ecnt]=getint();
w[ecnt]=getint();
if(!LCT.connect(u,v)){
LCT.link(u,ecnt);
LCT.link(v,ecnt);
ans+=w[ecnt];++tot;
continue;
}
int pos=LCT.query(u,v);
if(pos<=n||w[pos]<=w[ecnt])continue;
LCT.cut(from[pos],pos);
LCT.cut(to[pos],pos);
ans-=w[pos];
LCT.link(u,ecnt);
LCT.link(v,ecnt);
ans+=w[ecnt];
}
if(tot==n-1)cout<<ans;
else cout<<"orz";
return 0;
}