HDU1102 - Constructing Roads 用优先队列优化Prim最小生成树

HDU1102 - Constructing Roads : http://acm.hdu.edu.cn/showproblem.php?pid=1102

题意 : 给你N个村庄,接下来是N行输入,第 i 行的第 j 个数字代表的是编号为 i 的村庄到编号为j的村庄的距离.例如 : 0  2  5. 表示村庄1到自己的距离为0,到村庄2的距离为2,到村庄3的距离是5,N行输入后又有Q行输入,每行两个整数x, y.表示x和y之间已经修好路了.问要将所有村庄连在一起,最少要修多长的公路.

思路 : 就是用最小生成树求解,,,,,,Prim + 优先队列 可节省时间.

代码 :

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN = 111;
const int Inf = 1<<30;
int Map[MAXN][MAXN],Vis[MAXN],Dist[MAXN],Ans;
int N,Q;
int x,y;
void Initial()
{
	Ans = 0;
	fill(Vis,Vis + MAXN,0);
	fill(Dist,Dist + MAXN,Inf);
}
struct Node{
	int v,len;//v是编号,len是v到目标集合的距离(将所有已经连在一起的村庄看成一个集合)
	bool friend operator <(Node x,Node y)//用优先队列取出距离 已经连好的村庄 最近的村庄编号 
	{
		return x.len > y.len;
	}
};
void Prim()
{
	priority_queue<Node>Edge;
	Node Now;
	Now.v = 1,Now.len = 0;//假设先从第一个村庄开始,从其他的编号开始也可以,但是 len一定是 0 
	Edge.push(Now);
	while(!Edge.empty())
	{
		Now = Edge.top();
		Edge.pop();
		if(Vis[Now.v])continue;//已经在集合里,不再访问 
		Vis[Now.v] = 1;//否则标记为访问
		Ans += Now.len;//同时把当前节点 v到目标集合的距离len加到答案里,优先队列里取出来的可以保证是最短的路
		for(int i = 1;i <= N;i++)
		{
			if(!Vis[i] && Map[Now.v][i] < Dist[i])//满足此条件则可以加入队列 
			{
				Node Next;
				Next.v = i;
				Next.len = Dist[i] = Map[Now.v][i];
				Edge.push(Next); 
			}
		}
	}
	printf("%d\n",Ans);
}
int main()
{
	while(~scanf("%d",&N))
	{
		Initial();
		for(int i = 1;i <= N;i++)
			for(int j = 1;j <= N;j++)
				scanf("%d",&Map[i][j]);
		scanf("%d",&Q);
		while(Q--)
		{
			scanf("%d%d",&x,&y);//x,y已经相连 
			Map[x][y] = Map[y][x] = 0;
		}
		Prim();
	}
	return 0;
} 


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值