链接
题目描述
现在有n个点,每次可以把两个点连接,并花费一定的费用,把所有点连接起来之后,要求一个点权最小的点
样例输入
输入1:
3
0 6 9
6 0 4
9 4 0
7 7 7
输入2:
3
0 17 20
17 0 10
20 10 0
15 9 12
输入3:
5
0 3 12 15 11
3 0 14 3 20
12 14 0 11 7
15 3 11 0 15
11 20 7 15 0
5 10 10 10 10
样例输出
输出1:
17
输出2:
34
输出3:
28
思路
最小生成树的模板题,连个0号点,费用是点权,然后点之间连边,跑最小生成树就好了
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
ll n, x, minx = 1e9, ans, t;
ll h[1000005], fa[1000005];
struct node
{
ll from, to, next, val;
}g[10000005];
void add(int x, int y, ll val)
{
g[++t] = (node){x, y, h[x], val}; h[x] = t;
}
void addx(int x, int y, ll val)
{
g[++t] = (node){x, y, h[x], val}; h[x] = t;
g[++t] = (node){y, x, h[y], val}; h[y] = t;
}
bool cmp(node i, node j)
{
return i.val < j.val;
}
int find(int x)
{
if(fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
ll read()
{
ll x = 0, flag = 1; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') flag = -1; ch = getchar();}
while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0'; ch = getchar();}
return x * flag;
}
int main()
{
n = read();
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
{
x = read();
if(i != j) add(i, j, x), fa[i] = i;
}
for(int i = 1; i <= n; ++i){
x = read();
addx(0, i, x);
}
sort(g + 1, g + t + 1, cmp);
int tot = 0;
for(int i = 1; tot < n && i <= t; ++i)
{
int from = g[i].from;
int to = g[i].to;
int xx = find(from);
int yy = find(to);
if(xx != yy) {
fa[max(xx, yy)] = min(xx, yy);
tot++;
ans += g[i].val;
}
}
printf("%lld", ans);
return 0;
}