试题编号: | 201609-4 |
试题名称: | 交通规划 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 G国国王来中国参观后,被中国的高速铁路深深的震撼,决定为自己的国家也建设一个高速铁路系统。 输入格式 输入的第一行包含两个整数n, m,分别表示G国城市的数量和城市间铁路的数量。所有的城市由1到n编号,首都为1号。 输出格式 输出一行,表示在满足条件的情况下最少要改造的铁路长度。 样例输入 4 5 样例输出 11 评测用例规模与约定 对于20%的评测用例,1 ≤ n ≤ 10,1 ≤ m ≤ 50; |
Dijkstra算法简介:属于单源最短路径算法,要求邻接表的边权重恒为正,通过从一个源点出发,找出其能到达的所有点加入优先队列(以到达点的长度最短优先),这样从堆栈拿出来的边连接的点即为源点到达该点的最短路径。
解释:对于源点来说,他所连接的最短边所连点必为到该点的最短路径(因为权重为正),从队列取出该边后,再找出其到达点,判断该点通过一条边所能到达的未被自堆栈取出的点(自堆栈取出的就说明到达该点以是最短路径),再对这些点进行松弛操作,更新其到达该点的最短路径后加入堆栈。直至所有点都判断完毕或达到终止条件。
在路径最短的同时让新增的边最短。
#include "stdafx.h"
#define INF (0x3f3f3f3f)
using namespace std;
struct Edge {
int to, lenth; //连通城市,路程
Edge() {};
Edge(int too, int lenthh) {
to = too; lenth = lenthh;
}
bool operator<(const Edge S)const {
return lenth > S.lenth;
}
};
vector<Edge>Edges[10005];
bool Flag[10005]; //通过0/1区分是否找到
long long Dis[10005];
int Add[10005];
priority_queue<Edge>Save;
void Dijkstra(int Start,int To)
{
memset(Flag, 0, sizeof(Flag));
memset(Dis,INF, sizeof(Dis));
memset(Add, INF, sizeof(Add));
Dis[Start] = 0;
Add[Start] = 0;
Save.push(Edge(Start, Dis[Start]));
while (!Save.empty())
{
Edge Front = Save.top(); //上一个到达的点
Save.pop();
//if (Front.to == To)
// return;
if (Flag[Front.to])
continue;
Flag[Front.to] = 1;
for (int i = 0; i < Edges[Front.to].size(); i++) //松弛操作
{
Edge E = Edges[Front.to][i];
if (!Flag[E.to])
{
if (Dis[E.to] > Dis[Front.to] + E.lenth)
{
Dis[E.to] = Dis[Front.to] + E.lenth;
Add[E.to] = E.lenth;
Save.push(Edge(E.to,Dis[E.to]));
}
else if (Dis[E.to] == Dis[Front.to] + E.lenth)
Add[E.to] = min(E.lenth, Add[E.to]);
}
}
}
}
int main()
{
int i, j, N, M;
cin >> N >> M; //表示G国城市的数量和城市间铁路的数量
for (i = 0; i < M; i++)
{
int x, y, lenth;
cin >> x >> y >> lenth;
Edges[x].push_back(Edge(y, lenth));
Edges[y].push_back(Edge(x, lenth));
}
Dijkstra(1,N);
long long Sum = 0;
for (i = 1; i <= N; i++)
{
Sum += Add[i];
}
cout << Sum;
cin >> N;
return 0;
}