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

hiho一下 第二十八周 最小生成树三·堆优化的Prim算法

2017年03月02日 ⁄ 综合 ⁄ 共 1929字 ⁄ 字号 评论关闭
时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

回到两个星期之前,在成功的使用Kruscal算法解决了问题之后,小Ho产生了一个疑问,究竟这样的算法在稀疏图上比Prim优化之处在哪里呢?

提示:没有无缘无故的优化!

输入

每个测试点(输入文件)有且仅有一组测试数据。

在一组测试数据中:

第1行为2个整数N、M,表示小Hi拥有的城市数量和小Hi筛选出路线的条数。

接下来的M行,每行描述一条路线,其中第i行为3个整数N1_i, N2_i, V_i,分别表示这条路线的两个端点和在这条路线上建造道路的费用。

对于100%的数据,满足N<=10^5, M<=10^6,于任意i满足1<=N1_i, N2_i<=N, N1_i≠N2_i, 1<=V_i<=10^3.

对于100%的数据,满足一定存在一种方案,使得任意两座城市都可以互相到达。

输出

对于每组测试数据,输出1个整数Ans,表示为了使任意两座城市都可以通过所建造的道路互相到达至少需要的建造费用。

样例输入
5 29
1 2 674
2 3 249
3 4 672
4 5 933
1 2 788
3 4 147
2 4 504
3 4 38
1 3 65
3 5 6
1 5 865
1 3 590
1 4 682
2 4 227
2 4 636
1 4 312
1 3 143
2 5 158
2 3 516
3 5 102
1 5 605
1 4 99
4 5 224
2 4 198
3 5 894
1 5 845
3 4 7
2 4 14
1 4 185
样例输出
92
#include <cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define N 100002
#define M 1000002
struct edge
{
	int u;
	int v;
	int len;
};
edge a[M];
int rear;
vector<edge> Q[N];//顶点对应的邻接表
int visited[N];//记录是否已经置于最小生成树集合中

void init(int n)
{
	for(int i=1;i<=n;i++)
		visited[i] = 0;
}

void ins()//向堆添加数据
{
	int i = rear, j = i/2;
	edge temp = a[rear];
	while (j>=1 && temp.len < a[j].len)
	{
		//cout << "test" << endl;
		a[i] = a[j];
		i = j;
		j = j / 2;
	}
	a[i] = temp;
}

void del()//删除堆的根
{
	if (rear < 1)
		return;
	edge temp = a[1] = a[rear];
	rear--;
	int i = 1,j=2*i,lower=i;
	while (j <= rear)
	{
		//cout << "test" << endl;
		lower = j;
		if (j + 1 <= rear && a[j].len > a[j + 1].len)
			lower = j + 1;
		if (temp.len > a[lower].len)
		{
			a[i] = a[lower];
			i = lower;
			j = i*2;
		}
		else
		{
			break;
		}
	}
	a[i] = temp;
}

int prim(int n)
{
	int sum=0;
	vector<edge>::iterator it;
	for(it = Q[1].begin();it!=Q[1].end();it++)
	{
		edge e = *it;
		if(visited[e.v])
			continue;
		rear++;
		a[rear]=e;
		ins();
	}
	visited[1] = 1;
	int count = 1;
	while(1)
	{
		while(visited[a[1].v])
			del();
		//cout<<a[1].v<<endl;
		sum+=a[1].len;
		count++;
		if(count == n)
			break;
		int v = a[1].v;
		visited[v] = 1;
		del();
		vector<edge>::iterator it;
		for(it = Q[v].begin();it!=Q[v].end();it++)
		{
			edge e = *it;
			if(visited[e.v])
				continue;
			rear++;
			a[rear]=e;
			ins();
		}
	}
	return sum;
}

int main()
{
	int m,n,u,v,len;
	if(scanf("%d%d",&n,&m)==2)
	{
		rear=0;
		init(n);
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&u,&v,&len);
			edge temp1;
			temp1.u = u;
			temp1.v = v;
			temp1.len = len;
			edge temp2;
			temp2.u = v;
			temp2.v = u;
			temp2.len = len;
			Q[u].push_back(temp1);
			Q[v].push_back(temp2);
		}
		printf("%d\n",prim(n));
	}
	return 0;
}

抱歉!评论已关闭.