最小生成树问题
解决这道题的思想体现了对Kruskal算法的深刻理解。
每当我们从排序好的边的数组中取出一条边准备连接时,这条边一定比它两个端点所对应的联通图的边集合中最小的边还要小。。基于这样的思想我们就能够求解出这道题。
- 这其中有一点需要注意的是,原题中所说的添加的新的边是并不存在的。这也就是说这条添加的边的长度是我们可以人为随意决定的
#include<iostream>
#include<map>
#include<vector>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<bitset>
#include<stack>
#include<cstring>
using namespace std;
#define MAX 10000
struct Edge
{
int from, to, w;
};
vector<Edge>edges;
int fa[MAX];
int de[MAX];
void init(int n)
{
for (int i = 1; i <= n; i++)
{
fa[i] = i;
de[i] = 1;
}
}
int find(int x)
{
if (x == fa[x])
return x;
else
{
return fa[x] = find(fa[x]);
}
return 0;
}
void merge(int l, int r)
{
int lf = find(l);
int rf = find(r);
if (lf == rf)return;
else
{
fa[lf] =rf;
de[rf] += de[lf];
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sb.txt", "r", stdin);
#endif // !ONLINE_JUDGE
int N;
cin >> N;
for (int i = 0; i < N; i++)
{
int t;
cin >> t;
t--;
edges.clear();
for (int j = 0; j < t; j++)
{
int from, to, w;
cin >> from >> to >> w;
edges.push_back({ from,to,w });
}
sort(edges.begin(), edges.end(), [](Edge l, Edge r) {return l.w < r.w; });
long long ans = 0;
init(t+1);
for (auto c : edges)
{
int from = c.from, to = c.to, w = c.w;
int lf = find(from);
int rf = find(to);
if (lf == rf)continue;
else
{
//我们能够保证现在正在填加进去的这条边一定是对应两个边集合的最小边
ans += (de[lf] * de[rf] - 1) * (w + 1);
merge(from,to);
}
}
cout << ans << endl;
}
return 0;
}