现在的位置: 首页 > 综合 > 正文

[hoj 2507]The Bug Sensor Problem[第k长路]

2017年12月13日 ⁄ 综合 ⁄ 共 1380字 ⁄ 字号 评论关闭

题意:

给出一些点的坐标, 求这些点之间的第k长边.

本来的描述是, 一些点, 有效距离之内可以传送数据, 有效距离也表示耗电量. 可以放k个收发器, 收发器的有效距离无穷大. 所有点的耗电量设为相同, 问此时单点耗电量最小是多少.

思路:

先求最小生成树, 放k个传感器的话, 可以省去k-1条边(就是直接发走而不需要走这条边), 那么求出第k长边即可.

特殊的,未加优化的prim:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>

using namespace std;

#define Maxn 100005
#define INF 0x3f3f3f3f

struct Point
{
	double x,y;
}point[Maxn];

double dist[Maxn];
int vis[Maxn];
int s,p;
int m;
double ans[Maxn];

double getDis(Point a,Point b)
{
	return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
/**
prim算法的基本思路:
MST点集A和未加入MST点集~A, 每次从~A中找到到A中的点距离最近的点, 加入A. 重复这个过程, 直到~A为空.
要点是找到那个"距离最近的点"
*/
void prim()
{
	dist[0] = 0;//每次都从0这个点出发
	for(int i=1;i<p;i++)
	{
		dist[i] = INF;//初始化为正无穷, 还没开始扩展
	}
	memset(vis,0,sizeof(vis));//都未拜访
	m = 0;//ans的游标
	for(int i=0;i<p;i++)//遍历每一个点,i
	{
		double mi = INF;
		int mik;//存最近距离和最近点
		for(int j=0;j<p;j++)//遍历每一个点,j
		{
			if(dist[j]<mi && !vis[j]) mi = dist[j],mik = j;//找到最近距离和最近点,通过初始化启动算法
		}//dist[j]表示j点到A集合的最小距离.
		ans[m++] = mi;
		vis[mik] = 1;
		for(int j=0;j<p;j++)//本题比较特殊,给的是点,可以直接计算邻接的边,松弛.
		{//mik是新加点, 每次只需更新这一点.
			if(dist[j]> getDis(point[mik],point[j])) dist[j] = getDis(point[mik],point[j]);
		}
	}
}
int main()
{
	int w;
	double a,b;
	scanf("%d",&w);
	while(w--)
	{
		p = 0;
		scanf("%d",&s);
		while(scanf("%lf",&a)==1 && a!=-1)
		{
			scanf("%lf",&b);
			point[p].x = a,point[p].y = b;
			p++;
		}
		prim();
        sort(ans+1,ans+m);
        //第一条边是0号点与MST所在连通分量的距离,为0,不参加边长的比较
        //m已经++过了,故可以直接用+m作为end指针.
        printf("%.0f\n",ceil(ans[p-s]));
	}
	return 0;
}

抱歉!评论已关闭.