pku openjudge 题目 新丛林道路

4:新丛林道路

总时间限制: 
1000ms 
内存限制: 
65536kB
描述

热带岛Lagrishan的长官最近遇到个棘手的问题。Lagrishan岛上有若干村镇,各个村镇之间互通的道路每年需要巨额维修费用。为了减少道路的维修费用,Lagrishan的长官不得不决定放弃维护岛上某些现有的道路。上面的地图显示了现在岛上所有正在使用的道路以及每条路每月的维修费用。在某些道路停用后,仍要保证每两个村镇之间有道路能够连通。长官现在要做的就是向上级汇报每月维修道路所需的最小费用是多少,同时保证每两个村庄都有道路连通。上图中,左图表示的是目前岛上的所有道路,右图展示的是每月维修费用最少——216刀时应该保留哪些道路。你要做的就是编程来解决这个问题。

输入

输入包括100组数据,最后结束行内容只有一个0.每组数据第一行是一个整数n,告知村镇的总数目,1 < n < 27,村镇的名字分别用字母表的前n个大写字母表示。一组数据一共n行,在接下来的n-1行数据中,每行以村镇名字作为开头,名字后面紧跟一个整数k,用以表示该村镇到后面出现的其他村镇的道路条数。如果k > 0,本行接下来的内容就是这k条道路的信息——每项信息的内容为:道路另一端的村镇名字、道路维修费用/月。维修费是小于100的正整数。所有的数据项之间用一个空格作为分隔。所有道路的总条数不会超过75.每个村镇到其他村镇的道路总数不会超过15条。在下面的样例输入中,第一个样例数据是对上面所示地图的描述。

输出

对于每组测试数据都输出一个整数,即每月最少的维护费用总和。注意:蛮力搜索算法是无法在一分钟内完成解的计算的

样例输入
9
A 2 B 12 I 25
B 3 C 10 H 40 I 8
C 2 D 18 G 55
D 1 E 44
E 2 F 60 G 38
F 0
G 1 H 35
H 1 I 35
3
A 2 B 10 C 40
B 1 C 20
0
样例输出
216
30
提示
两个村庄间可能存在多条代价不同的路

思路:使用prm算法,以临街矩阵的数据结构计算最小支撑数、
注意和技巧 :在邻接矩阵的构建的时候,寻则两点之间最小的路作为两点之间的权 
                  prim算法是要把一个点的所有的边存入到最小堆中,所以一定要把这个点的行和列都遍历一遍
                  养成邻接矩阵学习的好习惯,无向图只存储上半区,有向图才全部使用

据图的代码如下

#include<iostream>
#include<queue>
#include<stdio.h>
#include<stdlib.h>
#include<vector>
#include<algorithm>
#include<functional>
#include<cstring>
using namespace std;

//这道题采用最小支撑数的写法
#define maxn 27
int data[maxn][maxn];//临街矩阵
class e
{
public:
	int s,d,len;
	e(int a=0,int b=0,int c=0)
	{
		s=a;
		d=b;
		len=c;
	}
	bool operator<(const e & b)const
	{
		return len>b.len;
	}
};
int n;
priority_queue<e> H;//建立一个最小堆
char tems[3],temd[3];
vector<e> ans;
bool marked[maxn];
int main()
{
	while(scanf("%d",&n))
	{
		if(n==0)
		{
			break;
		}
		memset(data,0,sizeof(data));
		ans.clear();
	    while(!H.empty())
		{
			H.pop();
		}
		memset(marked,0,sizeof(marked));
		for(int i=1;i<n;i++)
		{
			scanf("%s",tems);
			tems[0]-='A';
			int numofe, lenofe;
			scanf("%d",&numofe);
		    for(int j=0;j<numofe;j++)
			{
				scanf("%s",temd);
				temd[0]-='A';
				scanf("%d",&lenofe);
				if(lenofe<data[tems[0]][temd[0]]||data[tems[0]][temd[0]]==0)
					data[tems[0]][temd[0]]=lenofe;

			}
		}
	    int s;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				if(data[i][j]!=0)
				{
					s=i;
					goto down;
				}
			}
		}
		down:
		marked[s]=true;
		
		int num=0;
		do
		{
			bool find=false;
			for(int i=0;i<n;i++)
			{
				if(data[s][i])
				{
					H.push(e(s,i,data[s][i]));
				}
				if(data[i][s])
				{
					H.push(e(s,i,data[i][s]));//这个操作一定不要往了,我们要把遍历点的所有临边放入到最小堆中
				}
			}
			e t;
			while(!H.empty())
			{
				t=H.top();
				H.pop();
				if(!marked[t.d])
				{
					num++;
					marked[t.d]=true;
					find=true;
					break;
				}
			}
			if(!find)
			{
				printf("error");
			}
			ans.push_back(t);
		    s=t.d ;
			

		}
		while(num<n-1);
		int sum=0;
		for(int i=0;i<n-1;i++)
		{
			sum+=ans[i].len ;
		}
		printf("%d\n",sum);
	}
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Unity3D丛林越野是一款基于Unity引擎开发的游戏。游戏中玩家将扮演一位驾驶各种越野车辆穿越丛林的角色。游戏拥有精美的画面和逼真的物理效果,为玩家提供了真实的驾驶体验。 在游戏中,玩家需要驾驶越野车辆穿越丛林,跳过各种障碍物,解开各种谜题,探索未知的区域。玩家需要注意驾驶车辆的速度和方向,合理利用加速和刹车,以便在狭窄的道路上灵活应对。 游戏中设有多个关卡,各具挑战性。每个关卡都有不同的地形和环境,玩家需要根据具体情况调整驾驶策略。有些关卡需要在大量石头和树木之间穿行,有些关卡需要在沼泽地或河流中行驶。而且,有些关卡会有特殊的动态元素,如滚木、倒塌的桥梁等,增加了游戏的难度和挑战。 在游戏中,玩家还可以通过收集道具和解锁的车辆、升级车辆性能等方式提升游戏体验。游戏拥有丰富的内容和多样化的玩法,玩家可以根据自己的喜好和技能水平选择不同的策略和挑战。 总之,Unity3D丛林越野是一款刺激有趣的游戏,通过驾驶越野车穿越丛林来进行冒险和挑战。精美的画面和逼真的物理效果为玩家提供了真实的驾驶体验。不同的关卡和道具增加了游戏的难度和趣味性,使游戏更具挑战性。是否尝试一下这款游戏呢? ### 回答2: Unity3D丛林越野是一款非常有趣和具有挑战性的游戏。玩家扮演一个冒险者,需要在丛林中穿越各种障碍和险阻,最终达到终点。这个游戏采用了Unity3D引擎开发,因此拥有出色的图形和物理效果。 在游戏中,玩家需要控制角色行走,跳跃,滑行等操作来应对各种难题。丛林中充满了各种道具和道路选择,玩家需要善于利用它们来克服困难。同时,玩家还要小心丛林中的危险动物和植物,它们可能对角色造成伤害。 除了普通的关卡挑战,游戏还提供了时间竞赛模式和多人对战模式,让玩家能够和朋友一起享受丛林越野的乐趣。在时间竞赛模式中,玩家需要通过快速准确地完成关卡来获得最佳成绩。而在多人对战模式中,玩家可以和其他玩家一起较量,看谁能够更快速地到达终点。 Unity3D丛林越野游戏在游戏性方面非常出色。通过不断地挑战自我和改进技巧,玩家可以提高自己的游戏水平。同时,丛林越野的具体地图设计也非常精细,玩家可以欣赏到美丽的丛林风景。 总之,Unity3D丛林越野是一款令人兴奋和具有挑战性的游戏。它提供了丰富的关卡和多种游戏模式,让玩家可以尽情享受探险和竞争的乐趣。无论是单人挑战还是与朋友共同游戏,都能让玩家度过一个令人难忘的游戏时光。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值