BLINNET - Bytelandian Blingors Network

传送门:BLINNET - Bytelandian Blingors Network

通过读题,不难发现,把这些点连接起来的最小成本,岂不是最小生成树?

现在先思考一下给出的城市名字需要如何处理?其实直接按照输入顺序标号就好了!

跑一遍最小生成树即可,注意多测清空。

处理最小生成树的策略是,把边按照成本从小到大排序,每次找一个最短的边,根据并查集思想判断是否已经将节点纳入树中,若纳入树中,则不考虑这条边,若尚未纳入树中,就记录成本,并且用并查集做好标记。

见代码:

#include <bits/stdc++.h>
#define N 10010
#define M 1000010
using namespace std;

int n ,m ,ans ,tot ,cnt ,fa[N];
struct Edge{int u ,v ,w;}e[M];

void add(int u,int v,int w) {
	++ tot;
	e[tot].u = u;
	e[tot].v = v;
	e[tot].w = w;
}
int find(int x) {
	return fa[x] == x ? fa[x]:fa[x] = find(fa[x]);
}
bool cmp(Edge a,Edge b) {
	return a.w < b.w;
}
void search() {
	sort(e+1 ,e+1+tot ,cmp);
	for (int i = 1; i <= tot; ++ i) {
		int u = find(e[i].u) ,v = find(e[i].v);
		if(u == v) continue;
		ans += e[i].w;
		++ cnt;
		fa[v] = u;
		if(++ tot == n-1) break;
	}
	printf("%d\n" ,ans);
}
int main() {
    int t;
	scanf("%d" ,&t);
    string nam;
    for(int k = 1;k <= t; k++){
        memset(fa,0,sizeof(fa));
        memset(e,0,sizeof(e));
        tot = 0;
        ans = 0;
        cnt = 0;
        scanf("%d" ,&n);
	    for (int i = 1; i <= n; ++ i){
            cin >> nam;
            fa[i] = i;
            scanf("%d" ,&m);
            for (int j = 1 ,v ,w; j <= m; ++ j) {
		        scanf("%d %d",&v ,&w);
		        add(i ,v ,w);
	        }
        }
	    search();
    }
	return 0;
}
posted @ 2023-06-07 18:12  朝绾曦梦  阅读(6)  评论(0编辑  收藏  举报