我们把两个潜在丈夫连边,选了两个潜在丈夫,等价于选了一个公主
我们先考虑树的情况,选了 (k) 条边连接 (k+1) 个点,那么我们可以舍弃一个点(一个王子),剩下的 (k) 个王子可以完全匹配这 (k) 个公主
如果增加一条边,(k+1)个王子和(k+1)个公主,也是可以匹配的,这玩意就是个基环树
魔改 (kruskal)
令 (x=find(e[i].u),y = find(e[i].v)),(d)数组表示(i)是否是基环树,(0)无环,(1)有环,众所周知
树+树=树,基环树+树=基环树
(1.x ot=y&&(d[x]~||~d[y])=1),说明至少有一个不是基环树,可以合成一个树或基环树,加边权,(d[x]=d[x]~and~d[y])
(2.x=y),(d[x])只能等于(0),即树,加一条边成基环树,(d[x])变成(1)
struct Edge{int u,v,w;}e[N<<1]; int tot;
inline bool cmp(Edge a,Edge b){return a.w > b.w;}
int fa[N],n,m,num;bool d[N]; int ans;
int find(int x){return fa[x] == x ? x : fa[x] = find(fa[x]);}
int main(){
n = read(); m = read();
for(int i = 1;i <= m;++i){
e[i].u = read(); e[i].v = read(); e[i].w = read();
}
sort(e + 1,e + m + 1,cmp);
for(int i = 1;i <= n;++i) fa[i] = i,d[i] = 1;
for(int i = 1;i <= m;++i){
int u = find(e[i].u),v = find(e[i].v);
if(u != v && (d[u] || d[v]))
fa[v] = u,ans += e[i].w,d[u] = d[u]&d[v];
else if(u == v && d[u]) d[u] = 0,ans += e[i].w;
}
printf("%d
",ans);
}