思路:
建立一个超级源点S,
S向所有人连边,边权为雇佣费用
人与人之间存在连边,即交流费用
求最小生成树即可
注意几个细节:
- 对于最小生成树的边存储只能存一半,否则会超时。
- 千万不要打快读,我也不知道为什么比赛几个打快读的都炸掉了
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
//typedef long long int;
const int N = 1e6 + 10;
const int M = 1e3 + 10;
struct node {int u, v, w;} e[N];
int n, cnt, ans, t, f[N], a, tot;
bool cmp(node a, node b) {return a.w < b.w;}
int find(int x) {return (x == f[x]) ? x : (f[x] = find(f[x]));}
void unionn(int x, int y, int w) {f[x] = y; ans += w; tot++;}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
scanf("%d", &t);
if(i < j) e[++cnt] = (node){i, j, t};
}
for(int i = 1; i <= n; i++)
scanf("%d", &a), f[i] = i, e[++cnt] = (node){0, i, a};
sort(e + 1, e + 1 + cnt, cmp);
for(int i = 1; i <= cnt; i++)
{
int u = e[i].u, v = e[i].v;
int fx = find(u), fy = find(v);
if(fx != fy) unionn(fx, fy, e[i].w);
if(tot == n) break;
}
printf("%d\n", ans);
return 0;
}