最小生成树题单

最小生成树模板

Kruskal

#include <stdio.h>
#include <iostream>
#include <math.h>
#include <algorithm>

#define scd2(a, b) scanf("%d %d", &a, &b)
#define scd3(a, b, c) scanf("%d %d %d", &a, &b, &c)
#define prd(a) printf("%d\n",a)
#define fr(a,b,c) for(int a=b;a<=c;a++)
using namespace std;

struct rec{
	int a, b, c;
} edge[100100];
int fa[100100];

bool cmp(rec x, rec y){
	return x.c < y.c;
}

int get(int x) {
	if (x == fa[x]) return x;
	return fa[x] = get(fa[x]);
}

int main(){
	int n, m;
	scd2(n, m);//
	fr(i, 1, m){
		scd3(edge[i].a, edge[i].b, edge[i].c);
	}
	//按照边权排序 
	sort(edge + 1, edge + m + 1, cmp);
	
	//并查集初始化 
	fr(i, 1, n) fa[i] = i;
	
	//kruskal
	int ans = 0;
	fr(i, 1, m){
		int x = get(edge[i].a);
		int y = get(edge[i].b);
		if(x == y) continue;
		fa[x] = y;
		ans += edge[i].c;
	} 
	prd(ans);
	return 0;
} 

Prim

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>

#define scd2(a,b) scanf("%d %d",&a,&b)
#define scd3(a,b,c) scanf("%d %d %d",&a,&b,&c)
#define prd(a) printf("%d\n",a)
#define fr(a,b,c) for(int a=b;a<=c;a++)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int a[3010][3010], d[3010], n, m;
bool v[3010];

void prim(){
	mem(d, 0x3f);
	mem(v, 0);
	d[1] = 0;
	fr(i, 1, n){
		int x = 0;
		fr(j, 1, n){
			if(!v[j] && (x == 0 || d[j] < d[x])) x = j;
		}
		v[x] = 1;
		fr(y, 1, n){
			if(!v[y]) d[y] = min(d[y], a[x][y]);
		}
	}
}
int main(){
	scd2(n, m);
	mem(a, 0x3f);
	fr(i, 1, n) a[i][i] = 0;
	fr(i, 1, m){
		int x, y, z;
		scd3(x, y, z);
		a[y][x] = a[x][y] = min(a[x][y], z);
	}
	prim();
	int ans = 0;
	fr(i, 2, n) ans += d[i];
	prd(ans);
	return 0;
}

A - Jungle Roads

题意:给出节点和距离,求最小生成树

题解:

#include <iostream> 
#include <algorithm> 
#include <cstring>
using namespace std;
struct rec{
	int a, b, c;
} edge[100100];
int fa[100100];

bool comp(rec x, rec y){
	return x.c < y.c;
}

int get(int x){
    int temp = x;
    while(x != fa[x]) x = fa[x];
    while(temp != fa[temp]){
        int t_temp = temp;
        temp = fa[temp];
        fa[t_temp] = x;
    }
    return x;
}

int kruskal(int villagenum,int waynum){
	
}

int main(){
	int t;
	while(cin >> t){
		if(t == 0) break;

		int o = 0;
		for(int i = 0; i < t - 1; i ++){
			char ch1;	cin >> ch1;
			int temp1;		cin >> temp1;
			for(int j = 0; j < temp1; j ++){
				char ch2;	cin >> ch2;
				edge[o].a = ch1 - 'A';
				edge[o].b = ch2 - 'A';
				cin >> edge[o].c;
				o ++;
			}
		}
		sort(edge, edge + o, comp);	//结构体数组排序写法 
		for(int i = 0; i < t; i ++){
			fa[i] = i;
		} 
		int ans = 0;
		for(int i = 0, j = 0; j < t - 1; i ++){
			int v1 = edge[i].a;
			int v2 = edge[i].b;
			v1 = get(v1);
			v2 = get(v2);
			if(v1 != v2){
				fa[v2] = v1;
				j ++;
				ans += edge[i].c;
			}
		}
		cout << ans << endl;
	}
	return 0;
}

B - Networking

题意:给出点边的个数和各个边的长度,求最小生成树

题解:

#include <iostream> 
#include <algorithm>
#include <stdio.h>
using namespace std;
struct rec{int x, y, z;} edge[500010];
int fa[100100], n, m, ans;
bool operator < (rec a, rec b){//用于sort排序 
	return a.z < b.z;
}

int get(int x){
	if(x == fa[x]) return x;
	return fa[x] = get(fa[x]);
}
int main(){
	while(true){
		cin >> n;
		if(n == 0) break;
		cin >> m;
		if(m == 0){
			cout << "0" << endl;
			continue;
		} 
		for(int i = 1; i <= m; i ++){
			scanf("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].z);
		}
		sort(edge + 1, edge + m + 1);//对权值进行排序 
		 
		for(int i = 1;i <= n; i ++) fa[i] = i;
		
		ans = 0;
		for(int i = 1; i <= m; i ++){
			int x = get(edge[i].x);
			int y = get(edge[i].y);
			if(x == y) continue;
			fa[x] = y;
			ans += edge[i].z;
		}
		cout << ans << endl;
	}
	
	return 0;
} 

C - Building a Space Station

题意:给出多个空间球,求任意两个球圆心之间的距离,如果距离大于两个半径和,那么就是(距离 - 半径)和,要不然就是0,然后求最小生成树。

题解:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;

struct rec{
    int a;
    int b;
    double c;
} edge[100100];
int fa[100100];

struct Ball{
    double x;
    double y;
    double z;
    double r;
} ball[100100];
 
int cmp(rec x, rec y){
    return x.c < y.c;
}
 
int get(int x){
    if (x == fa[x]) return x;
	return fa[x] = get(fa[x]);
}

int main(){
	int t;
    while(true){
    	cin >> t;
    	if(t == 0) break;
        
        for(int i = 1; i <= t ; i ++){
            fa[i] = i;
            cin >> ball[i].x >> ball[i].y >> ball[i].z >> ball[i].r;
        }
        
        int o = 0;
        double temp;
        for(int i = 1; i <= t; i ++){
        	for(int j = i + 1; j <= t; j ++){
                temp = sqrt((ball[i].x - ball[j].x)*(ball[i].x - ball[j].x) + (ball[i].y - ball[j].y)*(ball[i].y - ball[j].y) + (ball[i].z - ball[j].z)*(ball[i].z - ball[j].z));
                temp -= (ball[i].r + ball[j].r);
				if(temp < 0) temp = 0;
				
				o ++;
                edge[o].a = i;
                edge[o].b = j;
                edge[o].c = temp;
            }
        }
        
        sort(edge + 1, edge + o + 1, cmp);
        
        int flag = 1;
	    double ans = 0;
	    for(int i = 1; i <= o; i ++){
	        int x = get(edge[i].a);
	        int y = get(edge[i].b);
	        if(x != y){
	            fa[x] = y;
	            ans += edge[i].c;
	            flag ++;
	            if(flag == t) break;
	        }
	    }
        printf("%.3lf\n", ans);
    }
    return 0;
}

D - Constructing Roads

题意:

题解:


E - Truck History

题意:

题解:


F - Arctic Network

题意:

题解:


G - Highways

题意:

题解:


H - Agri-Net

题意:

题解:


I - Borg Maze

题意:

题解:


J - The Unique MST

题意:

题解:



K - 还是畅通工程

这题和B题几乎一样
题意:

题解:


L - Jungle Roads

题意:

题解:


M - 畅通工程再续

题意:给出小岛的坐标,要求任意两个岛可以形成通路。若有小岛到其他任意小岛的距离小于10或大于1000则输出oh!

题解:

#include <stdio.h>
#include <iostream>
#include <math.h>
#include <algorithm>
using namespace std;
int x[110], y[110], fa[110], s;
struct rec{
	int a, b;
	double c;
} edge[10100];

bool cmp(rec x, rec y){
	return x.c < y.c;
}

int get(int x) {
	if (x == fa[x]) return x;
	return fa[x] = get(fa[x]);
}

int main(){
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while(t --){
		int n, o = 0;
		cin >> n;
		for(int i = 1; i <= n; i ++){
			cin >> x[i] >> y[i];
		}
		
		double temp;
		for(int i = 1; i <= n; i ++){
			for(int j = i + 1; j <= n; j ++){
				temp = sqrt((double)((y[j] - y[i])*(y[j] - y[i]) + (x[j] - x[i])*(x[j] - x[i])));
				if(temp >= 10 && temp <= 1000){
					o ++;
					edge[o].a = i;
					edge[o].b = j;
					edge[o].c = sqrt((double)((y[j] - y[i])*(y[j] - y[i]) + (x[j] - x[i])*(x[j] - x[i])));
				}
			}
		}
		
		//排序 
		sort(edge + 1, edge + o + 1, cmp);
		
		//并查集 
		for(int i = 1; i <= n; i ++) fa[i] = i;
		
		int flag = 0;
		double ans = 0;
		for (int i = 1; i <= o; i ++){
			int x = get(edge[i].a);
			int y = get(edge[i].b);
			if(x != y){
				fa[y] = x;
				flag ++;
				ans += edge[i].c;
			}
		}
		if (flag == n - 1) printf("%.1f\n", ans * 100);
		else cout << "oh!" << endl;
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值