题目:Forsaken喜欢独一无二的树
思路:构造最小生成树的时候,直接计算每条可以加进最小生成树的边权和,然后减掉选中的唯一最小生成树的边权和,并将要选中的最小生成树的点加入点的并查集,最后得到的ans就是答案。复杂度是O(mlogm)。
ACcode:
```cpp
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 10;
int n, m, d[N];
ll ans=0;
struct node
{
int u, v, w;
} no[N];
bool cmp(node a,node b)
{
return a.w<b.w;
}
int F(int x)
{
return d[x] == x ? x : d[x] = F(d[x]);
}
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i++)
d[i] = i;
for(int u, v, w, i = 1; i <= m; i++)
{
cin >> no[i].u >> no[i].v >> no[i].w;
}
sort(no + 1, no + m + 1,cmp);
for(int i = 1; i <= m;)
{
int j;
for(j=i;j<=m;j++)
{
if(no[i].w==no[j].w)//如果存在相同的边,即最小生成树不唯一
{
if(F(no[j].u)!=F(no[j].v))
{
ans+=no[j].w;
}
}
else
{
break;
}
}//将所有可能的最小生成树的边都加入ans中
for(; i < j; i++)
{
int x = F(no[i].u), y = F(no[i].v);
if(x != y)
{
d[x] = y;
ans -= no[i].w;
}//将选中的作为唯一最小生成树的边值减去,并将其顶点加入并查集
}
}
cout << ans << endl;
return 0;
}