ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SP338 ROADS - Roads 题解

2021-12-23 21:04:45  阅读:152  来源: 互联网

标签:条边 int 题解 Roads cost ROADS include leqslant dis


Update

  • \(\texttt{2020.11.9}\) 修改了一下公式。

Content

给定一个有 \(n\) 个点 \(r\) 条边的带权有向图,其中第 \(i\) 条边的起始点是 \(s_i\),终点是 \(d_i\),长度是 \(l_i\),花费是 \(t_i\)。求在总费用不超过 \(k\) 的情况下从 \(1\) 到 \(n\) 的最短路径长度。

数据范围:\(1\leqslant s_i,d_i\leqslant n,2\leqslant n\leqslant 100,1\leqslant r,k\leqslant10000,1\leqslant l_i\leqslant100,1\leqslant t_i\leqslant 100\)。

Solution

两维 dijkstra,有点类似于 DP。

给出以下定义:

\(dis_{i,j}\):从点 \(1\) 到 \(i\),且刚好花费 \(j\) 的情况下的最短距离。
\(vis_{i,j}\):是否在花费刚好为\(j\)的情况下经过点 \(i\),是为 \(1\),否为 \(0\)。

那我们不难想出这样的方程:\(dis_{v,j+cost_{i}}=dis_{i,j}+v_i\)(前提:\(j+cost_i\leqslant k\)),其中:

  • \(cost_i\) 代表经过第 \(i\) 条边的花费;
  • \(v_i\) 代表第 \(i\) 条边的长度;
  • \(k\) 如题意所述。

具体实现和 dijkstra 类似,注意多组数据要清空数组和队列(如果不使用堆优化则无需考虑该点),特判核心代码中括号内的情况。

非常简明的一道最短路题目,做起来需要多动脑筋。

Code

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <queue>
using namespace std;

int T, n, k, r, s, d, l, t, h[20007], cnt, dis[107][10007], vis[107][10007], ans;
struct edge {
	int v, cost, to, nxt;
}e[20007];
priority_queue<pair<int, pair<int, int> > > q;

inline void a_e(int u, int v, int w, int cost) {
	e[++cnt] = (edge){w, cost, v, h[u]}; h[u] = cnt;
}
inline int read() {
	int f = 1, x = 0;
	char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-')	f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') {
		x = x * 10 + c - '0';
		c = getchar();	
	}
	return x * f;
}
inline int dijkstra() {
	for(int i = 1; i <= n; ++i)
		for(int j = 0; j <= k; ++j)
			dis[i][j] = 0x3fffffff;
	dis[1][0] = 0;
	q.push(make_pair(0, make_pair(0, 1)));
	while(!q.empty()) {
		int x1 = q.top().first, x2 = q.top().second.first, x3 = q.top().second.second;
		q.pop();
		if(vis[x3][x2])	continue;
		vis[x3][x2] = 1;
		for(int i = h[x3]; i; i = e[i].nxt) {
			int y = e[i].to, z = e[i].v, ko = e[i].cost;
			if(dis[y][x2 + ko] > dis[x3][x2] + z && x2 + ko <= k) {
				dis[y][x2 + ko] = dis[x3][x2] + z;
				if(!vis[y][x2 + ko])
					q.push(make_pair(-dis[y][x2 + ko], make_pair(x2 + ko, y)));
			}
		}
	}
	int ans = 0x3fffffff; 
	for(int i = 0; i <= k; ++i)
		ans = min(ans, dis[n][i]);
	return ans == 0x3fffffff ? -1 : ans;
}

int main() {
	scanf("%d", &T);
	while(T--) {
		memset(vis, 0, sizeof(vis));
		memset(e, 0, sizeof(e));
		memset(h, 0, sizeof(h));
		cnt = 0, ans = 0x3fffffff;
		while(!q.empty())	q.pop();
		scanf("%d%d%d", &k, &n, &r);
		for(int i = 1; i <= r; ++i) {
			scanf("%d%d%d%d", &s, &d, &l, &t);
			a_e(s, d, l, t);
		}
		printf("%d\n", dijkstra());
	}	
}

标签:条边,int,题解,Roads,cost,ROADS,include,leqslant,dis
来源: https://www.cnblogs.com/Eason-AC/p/15725206.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有