洛谷P2176 [USACO11DEC] RoadBlock S / [USACO14FEB]Roadblock G/S

题意

给定一张 n n n m m m 边的无向图,请选择一条边,将其边权加倍,最多可使最短路增长多少?

思路

暴力做法:枚举所有边,将其边权加倍,跑一遍最短路,取最大值。
优化:由于修改最短路以外的边对最短路没有影响(除了变小),所以只需要枚举最短路上的边。
至于给边权加倍,我们不需要在邻接表中直接查找这条边来进行,只需在跑最短路时,传入两个参数 ( d u , d v ) (du,dv) (du,dv) ,表示要加倍的边的两个端点,只要当前边相连的是这两个点,就把边权加倍。下面是这种方法的实现。

// s - Source vertex.
// <du, dv> -> Edge that needs to be doubled.
// The shortest distance is recorded in `dis`.
// The precursor of each point is recorded in `pre`.
auto dij = [&](int s, int du = -1, int dv = -1){
	priority_queue<PII, vector<PII>, greater<PII>> q;
	dis[s] = 0;
	q.push({0, s});
	
	while(q.size()){
		int u = q.top().second;
		q.pop();
		
		if(vis[u]) continue;
		vis[u] = true;
		

		for(auto &edge: G[u]){
			int v = edge.first, w = edge.second;
			// If the current edge needs to be doubled
			if((du == u && dv == v) || (du == v && dv == u)) w <<= 1;
			if(dis[v] > dis[u] + w){
				dis[v] = dis[u] + w;
				q.push({dis[v], v});
				// Record the precursor.
				if(du == -1 && dv == -1) pre[v] = u;
			}
		}
	}
};

代码

// Problem: P2176 [USACO11DEC] RoadBlock S / [USACO14FEB]Roadblock G/S
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2176
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<queue>
using namespace std;
#define int long long
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	int n, m;
	cin >> n >> m;
	
	vector<vector<PII>> G(n);
	for(int i = 0, u, v, w; i < m; i++){
		cin >> u >> v >> w;
		u--, v--;
		G[u].push_back({v, w});
		G[v].push_back({u, w});
	}
	
	
	vector<int> dis(n, INF), pre(n, -1);
	vector<bool> vis(n, false);
	
	
	auto dij = [&](int s, int du = -1, int dv = -1){
		priority_queue<PII, vector<PII>, greater<PII>> q;
		dis[s] = 0;
		q.push({0, s});
		
		while(q.size()){
			int u = q.top().second;
			q.pop();
			
			if(vis[u]) continue;
			vis[u] = true;
			

			for(auto &edge: G[u]){
				int v = edge.first, w = edge.second;
				if((du == u && dv == v) || (du == v && dv == u)) w <<= 1;
				if(dis[v] > dis[u] + w){
					dis[v] = dis[u] + w;
					q.push({dis[v], v});
					if(du == -1 && dv == -1) pre[v] = u;
				}
			}
		}
	};
	
	dij(0);
	int mind = dis.back(), ans = 0;
	
	for(int i = n - 1; pre[i] != -1; i = pre[i]){
		if(i == 0) continue;
		int u = pre[i], v = i;
		
		dis.assign(n, INF);
		vis.assign(n, false);
		
		dij(0, u, v);
		ans = max(ans, dis.back());
	}
	cout << ans - mind << endl;
	return 0;
}

相关推荐

  1. P2176 [USACO11DEC] RoadBlock S / [USACO14FEB]Roadblock G/S

    2024-07-10 05:04:04       27 阅读
  2. P3008 [USACO11JAN] Roads and Planes G

    2024-07-10 05:04:04       22 阅读
  3. 题解】 P1696 [USACO18JAN] Blocked Billboard II B

    2024-07-10 05:04:04       27 阅读
  4. 【题解】 P9183 [USACO23OPEN] FEB B

    2024-07-10 05:04:04       56 阅读
  5. P2957 [USACO09OCT] Barn Echoes G

    2024-07-10 05:04:04       57 阅读
  6. P2895 [USACO08FEB] Meteor Shower S

    2024-07-10 05:04:04       34 阅读
  7. P2179 [NOI2012] 骑行川藏

    2024-07-10 05:04:04       27 阅读
  8. [USACO18JAN] Cow at Large P

    2024-07-10 05:04:04       19 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 05:04:04       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 05:04:04       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 05:04:04       57 阅读
  4. Python语言-面向对象

    2024-07-10 05:04:04       68 阅读

热门阅读

  1. ESP8266 Soft WDT reset

    2024-07-10 05:04:04       30 阅读
  2. Python程序打包成EXE文件指南

    2024-07-10 05:04:04       25 阅读
  3. MongoDB 全文检索

    2024-07-10 05:04:04       22 阅读
  4. threejs

    2024-07-10 05:04:04       24 阅读
  5. python 进阶教程--PIL图像处理

    2024-07-10 05:04:04       25 阅读
  6. CSS 图标:简化设计,优化用户体验

    2024-07-10 05:04:04       29 阅读
  7. C# 中使用模式匹配 备忘

    2024-07-10 05:04:04       26 阅读
  8. 【selenium】元素等待

    2024-07-10 05:04:04       21 阅读
  9. HTMLtable表转C#DataTable

    2024-07-10 05:04:04       32 阅读
  10. WPF设置全局样式

    2024-07-10 05:04:04       25 阅读