Light OJ - 1002 - Country Roads 题解

变形Dijkstra算法解析
本文介绍了一种变形的Dijkstra算法,该算法用于寻找图中从各节点到指定节点的路径,路径成本由所经过边的最大权值决定。文章通过一个具体的示例详细解释了算法的实现过程,并给出了完整的C++代码。

不是很难的题目,却搞得我好头痛,这里是应该了变形的Dijstra算法了,因为这里求最短路径不是把所有路径相加,而是把路径上所有的值取最大值,这个最大值越小,就说明结果最优,也不管你绕了多长的路。

另外值得注意的就是memset这个函数,看来很多人栽跟斗啊,这个函数只能用来清零,是不能用来初始化值的,因为它是按照字符来初始化值的,所以计算好也可以给整形清零,但是这次我用来给bool数组清零,结果出现奇怪的现象。还是使用fill这个函数或者是循环赋值吧,不能偷懒的了。

下面是题目:

I am going to my home. There are many cities and many bi-directional roads between them. The cities are numbered from0ton-1and each road has a cost. There aremroads. You are given the number of my citytwhere I belong. Now from each city you have to find the minimum cost to go to my city. The cost is defined by the cost of the maximum road you have used to go to my city.

For example, in the above picture, if we want to go from 0 to 4, then we can choose

1)0 - 1 - 4 which costs 8, as 8 (1 - 4) is the maximum road we used

2)0 - 2 - 4 which costs 9, as 9 (0 - 2) is the maximum road we used

3)0 - 3 - 4 which costs 7, as 7 (3 - 4) is the maximum road we used

So, our result is 7, as we can use 0 - 3 - 4.

Input

Input starts with an integerT (≤ 20), denoting the number of test cases.

Each case starts with a blank line and two integersn (1 ≤ n ≤ 500)andm (0 ≤ m ≤ 16000). The nextmlines, each will contain three integersu, v, w (0 ≤ u, v < n, u ≠ v, 1 ≤ w ≤ 20000)indicating that there is a road betweenuandvwith costw. Then there will be a single integert (0 ≤ t < n). There can be multiple roads between two cities.

Output

For each case, print the case number first. Then for all the cities (from0ton-1) you have to print the cost. If there is no such path, print'Impossible'.

Sample Input

Output for Sample Input

2

5 6

0 1 5

0 1 4

2 1 3

3 0 7

3 4 6

3 1 8

1

5 4

0 1 5

0 1 4

2 1 3

3 4 7

1

Case 1:

4

0

3

7

7

Case 2:

4

0

3

Impossible

Impossible


题目还是挺有意思的,变形的Dijstra,学好这个算法还是很有必要的。
标准的Dijstra参考资料:
http://www.geeksforgeeks.org/greedy-algorithms-set-6-dijkstras-shortest-path-algorithm/


#include <stdio.h>
#include <iostream>
#include <math.h>
#include <string>
#include <vector>
#include <assert.h>

using namespace std;

const static int MAX_COST = 20001;

int minDist(vector<int> &rs, bool *splitSet)
{
	int min_val = MAX_COST, id = -1;
	for (unsigned i = 0; i < rs.size(); i++)
	{
		if (!splitSet[i] && rs[i] < min_val)
		{
			min_val = rs[i];
			id = i;
		}
	}
	return id;
}

vector<int> findPaths(vector<vector<int> > &graph, const int sp)
{
	vector<int> rs(graph.size(), MAX_COST);
	bool *splitSet = new bool[graph.size()];
	for (unsigned i = 0; i < graph.size(); i++)
	{
		splitSet[i] = false;
	}
	rs[sp] = 0;

	for (unsigned i = 0; i < graph.size(); i++)
	{
		int id = minDist(rs, splitSet);
		if (-1 == id)break;//之后的都没路了

		splitSet[id] = true;
		for (unsigned j = 0; j < graph.size(); j++)
		{
			if (!splitSet[j] && -1 != graph[id][j])
			{
				int tmp = max(rs[id], graph[id][j]);
				rs[j] = min(rs[j], tmp);
			}
		}
	}
	delete [] splitSet;
	return rs;
}

void CountryRoads()
{
	int T = 0, n = 0, m = 0, u = 0, v = 0, w = 0, t = 0;
	cin>>T;
	for (int i = 0; i < T; i++)
	{
		cin>>n>>m;		
		vector<vector<int> > graph(n, vector<int>(n, -1));
		for (int j = 0; j < m; j++)
		{
			cin>>u>>v>>w;
			assert(0<=u && u<n && 0<=v && v<n);
			if (-1 == graph[u][v]) graph[u][v] = graph[v][u] = w;
			else graph[u][v] = graph[v][u] = min(graph[u][v], w);
		}
		cin>>t;
		vector<int> rs = findPaths(graph, t);
		cout<<"Case "<<i+1<<":"<<endl;
		for (unsigned i = 0; i < rs.size(); i++)
		{
			if (MAX_COST == rs[i]) cout<<"Impossible"<<endl;
			else cout<<rs[i]<<endl;
		}
	}
}
int main()
{
	CountryRoads();
	return 0;
}



### 东方博宜 OJ 1765 题解或解题思路 由于当前引用中并未直接提及东方博宜 OJ 平台编号为 1765 的题目内容及解法,以下将基于已有的引用信息和常规竞赛编程问题的解决方法,提供一种可能的分析与解答框架。 #### 可能的题目类型 根据东方博宜 OJ 平台的特点以及引用中的其他题目[^1],可以推测 1765 题目可能涉及以下领域之一: - 数据结构操作(如数组、链表、栈等) - 算法设计(如排序、搜索、动态规划等) - 字符串处理 - 数学计算 假设该题目属于常见算法题型之一,以下将从数据结构操作的角度进行分析。 #### 数据结构操作示例 若题目要求对一个序列进行多次操作(如插入、删除、排序等),可以参考引用 [4] 中的代码逻辑。以下是类似的实现方式: ```cpp #include <bits/stdc++.h> using namespace std; int main() { int n, m; // n: 初始序列长度, m: 操作次数 cin >> n >> m; vector<int> v; // 存储初始序列 for (int i = 0; i < n; i++) { int opt; cin >> opt; v.push_back(opt); } for (int i = 1; i <= m; i++) { int opt, x; cin >> opt >> x; vector<int>::iterator it = v.begin(); if (opt == 1) { // 插入 int y; cin >> y; v.insert(it + x, y); } else if (opt == 2) { // 删除 v.erase(it + x - 1); } else if (opt == 3) { // 排序 int y; cin >> y; sort(it + x - 1, it + y); } else if (opt == 4) { // 反转 int y; cin >> y; reverse(it + x - 1, it + y); } else { // 自定义操作 int y, z; cin >> y >> z; for (int j = --x; j < y; j++) { if (v[j] == z) { v.erase(it + j); j--; y--; } } } } for (int i = 0; i < v.size(); i++) { cout << v[i] << " "; } return 0; } ``` 此代码适用于多操作场景下的序列管理问题,具体功能已在注释中标明[^4]。 #### 字符串处理示例 如果题目涉及字符串操作,例如生成特定格式的输出,可以参考引用 [5] 的代码逻辑。以下是类似的应用: ```cpp #include <bits/stdc++.h> using namespace std; int main() { char c; int n; cin >> c >> n; for (int i = 1; i <= n; i++) { for (int j = 1; j <= n - i; j++) { cout << ' '; } for (int j = 1; j <= 2 * i - 1; j++) { cout << char(c + j - 1); } cout << endl; } return 0; } ``` 此代码用于生成字符三角形,可根据实际题目需求调整逻辑[^5]。 #### 解题思路总结 在没有明确题目描述的情况下,建议从以下几个方面入手: 1. 分析输入输出格式,明确问题核心。 2. 根据问题特点选择合适的数据结构或算法。 3. 编写代码时注意边界条件和特殊情况的处理。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值