E. 回家 (最短路)

Description
n n n 个城市,编号从 1 ∼ n 1 \sim n 1n 。小明的家所在城市编号为 x ( 1 ≤ x ≤ n ) x(1 \leq x \leq n) x(1xn) 。两个城市 u u u v v v 之间存在路径长度为 w w w 的单向路 < u , v > 。 <u, v>。 <u,v> 小 明想知道分别从 n n n 个城市出发,到达小明所在城市并返回的最短路径中最长的是多少?
Input Data
第一行是一个整数 T ( 1 ≤ T ≤ 100 ) T(1 \leq T \leq 100) T(1T100) ,表示样例的个数。
输入的第一行包含 3 个整数, n , e , x ( 1 ≤ n ≤ 1000 , 1 ≤ e ≤ 10000 , 1 ≤ x ≤ n ) n, e, x(1 \leq n \leq 1000,1 \leq e \leq 10000,1 \leq x \leq n) n,e,x(1n1000,1e10000,1xn) ,分别表示城市数量,路径数量以及小明所在城 市编号。
随后的 e e e 行,每行是一条路径,包含三个整数 u , v , w ( 1 ≤ u , v ≤ n , 1 ≤ w ≤ 1000 ) u, v, w(1 \leq u, v \leq n, 1 \leq w \leq 1000) u,v,w(1u,vn,1w1000) 。输入保证一定有解。
Output Data
每行输出一个样例的结果。
Sample Input
1
4 7 2
1 2 7
1 3 2
2 3 1
3 2 2
3 4 5
2 1 3
4 2 3
Sample Output
9

Tips: 分别建立正图和反图,对于x点,跑两次Dijkstra,求出该点到其他点的距离,然后求这两次的最小距离之和的最大值。

struct Node {
	int x, z;
	bool operator < (const Node& rhs) const {
		return z > rhs.z;
	}
};
void solve() {
	int n, e, s;
	cin >> n >> e >> s;
	vector<vector<pair<int,int>>> g(n + 1), h(n + 1);
	while (e--) {
		int u, v, w;
		cin >> u >> v >> w;
		g[u].push_back(make_pair(v, w));
		h[v].push_back(make_pair(u, w));
	}
	priority_queue<Node> pq;
	pq.push(Node{s, 0});
	vector<int> dis(n + 1, INT_MAX), vis(n + 1, 0), dis2(dis), vis2(vis);
	dis[s] = 0;
	while (!pq.empty()) {
		auto t = pq.top();
		int x = t.x;
		pq.pop();
		if (vis[x]) continue;
		vis[x] = 1;
		for (int i = 0; i < g[x].size(); i++) {
			auto y = g[x][i].first, z = g[x][i].second;
			if (dis[y] > dis[x] + z) {
				dis[y] = dis[x] + z;
				if (!vis[y]) {
					pq.push(Node{y, dis[y]});
				}
			}
		}
	}
	dis2[s] = 0;
	pq.push(Node{s, 0});
	while (!pq.empty()) {
		auto t = pq.top();
		pq.pop();
		int x = t.x;
		if (vis2[x]) continue;
		vis2[x] = 1;
		for (int i = 0; i < h[x].size(); i++) {
			auto y = h[x][i].first, z = h[x][i].second;
			if (dis2[y] > dis2[x] + z) {
				dis2[y] = dis2[x] + z;
				if (!vis2[y]) {
					pq.push(Node{y, dis2[y]});
				}
			}
		}
	}
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		ans = max(dis[i] + dis2[i], ans);
	}
	cout << ans << "\n";
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值