[洛谷P2176] [USACO14FEB] 路障Roadblock
Description
给定一张无向图,FJ在1号点,牛棚在n号点
FJ每次去牛棚都会按照最短路顺序(只走最短路)奶牛们可以让任意一条最短路上的边扩大2倍 此时就会出现一个比最短路更大的路的权值 即为增值
问 最大增值???
Solution
先跑一边dijkstra求出最短路 记录最短路权值为d 在求最短路的同时记录最短路的边 可以设一个数组pre,pre[i]表示i点是从哪个点转移过来的
另一个数组bian,bian[i] 表示从上一个点过来的边的编号
另开一个数组 记录最短路边的编号 枚举每个最短路的边 扩大2倍 再跑一遍dijkstra求出最短路权值 在每次中找到最大的权值ans
最后用ans - d即可
附:
至于边的修改 我们把边从2开始存 求另一个只需要^1 至于为啥我也不知道
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 #include <cstring> 5 #define pa pair<int, int> 6 using namespace std; 7 int n, m, num = 1; 8 int head[150000], dis[1200], vis[1200], pre[1200], bian[120]; 9 priority_queue<pa, vector<pa>, greater<pa> >q; 10 int b[1200]; 11 struct emmm 12 { 13 int next, to, dis; 14 }e[150000]; 15 void add (int from, int to, int dis) { 16 e[++num].next = head[from]; 17 e[num].to = to; 18 e[num].dis = dis; 19 head[from] = num; 20 } 21 void dijkstra() { 22 memset(dis, 0x3f3f3f, sizeof(dis)); 23 memset(vis, 0, sizeof(vis)); 24 dis[1] = 0; 25 q.push(make_pair(0, 1)); 26 while (!q.empty()) { 27 int now = q.top().second; 28 q.pop(); 29 if (vis[now]) continue; 30 vis[now] = 1; 31 for (int i = head[now];i;i = e[i].next) { 32 int v = e[i].to; 33 if (dis[v] > dis[now] + e[i].dis) { 34 dis[v] = dis[now] + e[i].dis; 35 pre[v] = now; 36 bian[v] = i; 37 q.push(make_pair(dis[v], v)); 38 } 39 } 40 } 41 } 42 int main() { 43 ios::sync_with_stdio(false); 44 cin >> n >> m; 45 int x, y, z; 46 for (int i = 1;i <= m; i++) { 47 cin >> x >> y >> z; 48 add(x, y, z); 49 add(y, x, z); 50 } 51 dijkstra(); 52 int now1 = n, sum = 0, ans = dis[n], kkk = 0; 53 while (now1 != 1) { 54 b[++sum] = bian[now1]; 55 now1 = pre[now1]; 56 } 57 for (int i = 1;i <= sum; i++) { 58 e[b[i]].dis<<=1; 59 e[b[i]^1].dis<<=1; 60 dijkstra(); 61 kkk = max(kkk, dis[n]); 62 e[b[i]].dis>>=1; 63 e[b[i]^1].dis>>=1; 64 } 65 cout << kkk - ans << endl; 66 return 0; 67 }