shortest path

本文介绍了解决一道特殊单源最短路径问题的方法,该问题要求路径上的边距离严格单调递增。通过将问题视为集合扩张过程,并按边权递增顺序处理,实现了有效的算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天做了hdu4479的一道题,是要求找到单源最短路径,同时路径上的边的距离需要是严格单调递增的。乍一看其已经不再符合贪心的结构,不能用dijkstra来直接处理。这里感觉要换下思路,即将建立单源最短路的过程看成是一个集合的扩张过程,其中通过保证扩张的过程是从边权递增的顺序进行以完成扩展,同时在每一轮中进行相应处理判断即可。另外确实要学习更多stl的巧妙用法了。

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <utility>
using namespace std;
#define MAXN 10003
#define INF 1e18
typedef long long ll;
typedef struct vertex {
	ll length;
	struct vertex(ll lengtho) { length = lengtho; }
}Vertex;
typedef struct edge {
	int fromCity;
	int toCity;
	ll length;
	struct edge(int fromCit, int toCit, ll wei) { fromCity = fromCit; toCity = toCit; length = wei; }
	bool operator < (const struct edge& a){ return length < a.length; }
}Edge;

int T, N, M;
vector<Edge > edges;
vector<Vertex > vertices;

void init()
{
	edges.clear();
	vertices.clear();
}
void input()
{
	scanf("%d %d", &N, &M);
	int city1, city2;
	ll weight;
	for (int i = 0; i < M; i++) {
		scanf("%d %d %lld", &city1, &city2, &weight);
		assert(city1 <= N&&city2 <= N);
		edges.push_back(Edge(city1 - 1, city2 - 1, weight));
	}
	sort(edges.begin(), edges.end());
}
void betterRelax(int left, int rigt)
{
	//printf("Relaxing between %d and %d\n", left, rigt);
	vector<pair<int, ll>> updateList;
	for (int i = left; i <= rigt; i++) {
		Edge temp = edges[i];
		int u = temp.fromCity;
		int v = temp.toCity;
		if (vertices[u].length != INF&&vertices[v].length > vertices[u].length + temp.length)
			updateList.push_back(make_pair(v, vertices[u].length + temp.length));
		if (vertices[v].length != INF&&vertices[u].length > vertices[v].length + temp.length)
			updateList.push_back(make_pair(u, vertices[v].length + temp.length));
	}
	for (int i = 0; i < updateList.size(); i++) {
		pair<int, ll> &temp = updateList[i];
		vertices[temp.first].length = min(vertices[temp.first].length, temp.second);
	}
}
void increasingShortestPath()
{
	for (int i = 0; i < N; i++)
		vertices.push_back(Vertex(INF));
	vertices[0].length = 0;
	int j;
	for (int i = 0; i < edges.size(); ) {
		for (j = i + 1; j < edges.size(); j++)
			if (edges[j].length > edges[i].length)
				break;
		betterRelax(i, j - 1);
		i = j;
	}
	if (vertices[N - 1].length >= INF)
		printf("No answer\n");
	else
		printf("%lld\n", vertices[N - 1].length);
}
int main()
{
	scanf("%d", &T);
	for (int i = 0; i < T; i++) {
		init();
		input();
		increasingShortestPath();
	}
	return 0;
}

(注:本题解题思路受http://blog.youkuaiyun.com/cquwel启发,在此表示领教了)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值