poj 2349 Arctic Network 最小生成树 kruskal

题目链接

                https://cn.vjudge.net/contest/245639#problem/D

题目大意

               将n个顶点连接起来, 使得边的权值之和最小,  而题目要输出的不是最小权值和, 而是在最小生成树上找出一条权值最大

              的边, 输出这条边的权值 ,当然是有前提的, 要先除去s-1条最大的边, 因为这s-1条边是无限制连接的.

题目分析

              采用kruskal法将选中的n-1条边存入一个数组sum中, 输出sum[n-1-s]即可, 现在来分析n-s-1怎么得来的

              根据树的性质: 一共有n个顶点, 所以树有n-1条边, 有s个卫星传输, 可使得s-1条边不限制传输, 所以还剩下n-1-(s-1)条边,

              我们要的就是这第 n-1-(s-1) 条边的权值

              而sum[0]是第1条边, sum[1]是第2条边, 所以第n-1-(s-1)条边就是sum[n-1-(s-1)-1] , 即sum[n-1-s].

 

               一开始写了好多遍都没过, 一直WA, 也找不出哪里有问题, 修修改改还是WA,   最后干脆把代码全部删掉重新写了一遍就直接AC了.

代码示例

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = 200000 + 5;

int per[maxn],n,m,s;
double sum[maxn];
struct node{ int from, to; double val; }e[maxn];
struct vet{ double x, y; }v[maxn];
int find(int x){ return per[x] == x ? x : per[x] = find(per[x]); }
bool cmp(node a, node b){ return a.val < b.val; }
void init()
{
	for (int i = 1; i <= n; i++) per[i] = i;
}
void input()
{
	for (int i = 1; i <= n; i++)
		cin >> v[i].x >> v[i].y;
	m = 0;
	for (int i = 1; i < n;i++)
	for (int j = i + 1; j <= n; j++)
	{
		e[m].from = i;
		e[m].to = j;
		e[m++].val = sqrt((v[i].x - v[j].x)*(v[i].x - v[j].x) + (v[i].y - v[j].y)*(v[i].y - v[j].y));
	}
	sort(e, e + m, cmp);
	//for (int i = 0; i < m; i++)
	//	printf("%d %d %lf\n", e[i].from, e[i].to, e[i].val);
}
void kruskal()
{
	int num = 0;
	for (int i = 0; i < m; i++)
	{
		int fa = find(e[i].from), fb = find(e[i].to);
		if (fa != fb)
		{
			per[fa] = fb;
			sum[num++] = e[i].val;
		}
	}
	printf("%.2lf\n", sum[n - s - 1]);
}
int main()
{
	int t; cin >> t;
	while (t--)
	{
		cin >> s >> n;
		init();
		input();
		kruskal();
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值