给定一个图,为最小生成树,加入若干边使得图变为完全图且MST不改变,问最小总权是多少
程序员文章站
2024-03-21 17:23:40
...
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define DBG printf("this is a input\n")
#define fi first
#define se second
#define mk(a, b) make_pair(a,b)
#define p_queue priority_queue
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b) {
return a / gcd(a, b) * b;
}
int T, n, fa[20000];
int scc[20000];
struct node{
int u ,v ,w;
bool operator < (const node& no) const{
return w < no.w;
}
}edge[20000];
int findroot(int x)
{
if(fa[x] == x)
return x;
return fa[x] = findroot(fa[x]);
}
bool merge(int x, int y)
{
int fax = findroot(x);
int fay = findroot(y);
if(fax != fay)
{
fa[fax] = fay;
return true;
}
return false;
}
int main(void)
{
cin>>T;
while(T --)
{
cin>>n;
for(int i = 1 ;i <= n ; i ++)
scc[i] = 1;
for(int i = 1 ; i <= n ; i ++)
fa[i] = i;
for(int i = 1 ; i <= n - 1 ; i ++)
cin>>edge[i].u>>edge[i].v>>edge[i].w;
sort(edge+1,edge+n);
int ans = 0;
for(int i = 1 ; i <= n - 1; i ++)
{
int u = edge[i].u , v = edge[i].v, w = edge[i].w;
int sx = findroot(u) , sy = findroot(v); //保留上一次的父亲,merge后会修改
if(merge(u,v)) //fa[fax] = fay 所以合并到v的联通块
{
ans += (scc[sx]*scc[sy]-1)*(w+1);
scc[sy] += scc[sx];
}
}
cout<<ans<<endl;
}
}
/*
2
5
1 2 1
2 3 2
3 4 3
4 5 4
*/
上一篇: poj 1797(最大生成树)
下一篇: POJ 3522 (生成树)