[USACO14FEB]路障Roadblock

题目:洛谷P2176。

题目大意:有n个点m条无向边,一个人要从1走到n,他会走最短路。现在可以让一条边的长度翻倍,求翻倍后这个人要多走多少距离。

解题思路:首先可以知道,翻倍肯定是在最短路上的某条边翻,否则他走的路不会变。我们先跑一遍最短路,记录下走的边,再枚举哪条边翻倍,然后跑最短路,记录下答案即可。

此题好像卡SPFA,于是我用堆优化Dijkstra秒杀。

时间复杂度$O(nm\log n)$。

C++ Code:

#include<cstdio>
#include<cstring>
#include<ext/pb_ds/priority_queue.hpp>
using namespace __gnu_pbds;
struct edge{
	int from,to,dis,nxt;
}e[10005];
struct heapnode{
	int u,d;
	bool operator<(const heapnode& rhs)const{return d>rhs.d;}
};
priority_queue<heapnode>q;
int n,m,head[10005],cnt,d[10005],prev[10005],prea[10005];
inline void addedge(int from,int to,int dis){
	e[++cnt]=(edge){from,to,dis,head[from]};
	head[from]=cnt;
	e[++cnt]=(edge){to,from,dis,head[to]};
	head[to]=cnt;
}
void dijkstra(){
	memset(d,0x3f,sizeof d);
	memset(prev,0,sizeof prev);
	q.push((heapnode){1,d[1]=0});
	while(!q.empty()){
		heapnode x=q.top();
		q.pop();
		int u=x.u;
		if(d[u]!=x.d)continue;
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(d[v]>d[u]+e[i].dis){
				d[v]=d[u]+e[i].dis;
				prev[v]=i;
				q.push((heapnode){v,d[v]});
			}
		}
	}
}
int main(){
	cnt=1;
	scanf("%d%d",&n,&m);
	for(;m--;){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		addedge(x,y,z);
	}
	dijkstra();
	memcpy(prea,prev,sizeof prea);
	int ans=d[n],mx=0;
	for(int i=prea[n];i;i=prea[e[i].from]){
		e[i].dis*=2;
		e[i^1].dis*=2;
		dijkstra();
		if(d[n]-ans>mx)mx=d[n]-ans;
		e[i].dis/=2;
		e[i^1].dis/=2;
	}
	printf("%d\n",mx);
	return 0;
}
时间: 2024-10-10 09:56:00

[USACO14FEB]路障Roadblock的相关文章

P2176 [USACO14FEB]路障Roadblock

题目传送门 十分值得一做的最短路,题目意思十分明确,一条边权值加倍后最多比加倍前的最短路花费多多少.首先看到m<=5000,第一念头就是跑m遍最短路,但是会严重超时,实际上是由于有些边的权值改变,对最短路没有造成任何影响,才导致了我们程序的严重超时,所以我们采取第一次跑最短路记路径的方法.开三个辅助数组path[].pre[]和edge[],path[]就是用来记最短路经过了哪些编号的边(邻接表存边),pre[i]表示走i号节点之前走的边,edge[i]表示到i号节点之前所经过的点,然后whil

P2176路障与P1186玛丽卡与P1491集合位置全面胜利

P2176 [USACO14FEB]路障Roadblock P1186 玛丽卡 P1491 集合位置 怎么又做到三倍经验,五年计划都超额完成了 这几道题像极了. 想起来不难吧,要让边改变之后与原来的最短路差值最大,就把最短路上的边改了呗. 用一个队列来记录最短路上的边,然后枚举这个队列里的元素,依次改变,刷出最大值. 代码有点不好写,这次我加上注释了. 不要问我为什么变量名怎么这么长,最近沉迷代码补全. P2176的代码: #include<bits/stdc++.h> using names

(寒假集训)Roadblock(最短路)

Roadblock 时间限制: 1 Sec  内存限制: 64 MB提交: 9  解决: 5[提交][状态][讨论版] 题目描述 Every morning, FJ wakes up and walks across the farm from his house to the barn.  The farm is a collection of N fields (1 <= N <= 250) connected by M bidirectional pathways (1 <= M

络谷 P2865 [USACO06NOV]路障Roadblocks

P2865 [USACO06NOV]路障Roadblocks 题目描述 Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. She does not want to get to her old home too quickly, because she likes the scenery along the way. She has decided t

洛谷P2237 [USACO14FEB]自动完成Auto-complete

洛谷P2237 [USACO14FEB]自动完成Auto-completeTrie树 1 #include <bits/stdc++.h> 2 #define For(i, j, k) for(int i=j; i<=k; i++) 3 #define Dow(i, j, k) for(int i=j; i>=k; i--) 4 #define LL long long 5 using namespace std; 6 inline int read() { 7 int x = 0

Roadblock

2428: Roadblock 时间限制: 1 Sec  内存限制: 64 MB提交: 17  解决: 6[提交] [状态] [讨论版] [命题人:admin] 题目描述 Every morning, FJ wakes up and walks across the farm from his house to the barn.  The farm is a collection of N fields (1 <= N <= 250) connected by M bidirectional

P3102 [USACO14FEB]秘密代码Secret Code

题目描述 Farmer John has secret message that he wants to hide from his cows; the message is a string of length at least 2 containing only the characters A..Z. To encrypt his message, FJ applies a sequence of "operations" to it, where an operation ap

java路障CyclicBarrier

当所有线程都执行到某行代码,才可已往下执行: package threadLock; import java.util.Random; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; pub

BZOJ 3445: [Usaco2014 Feb] Roadblock

Description 一个图, \(n\) 个点 \(m\) 条边,求将一条边距离翻倍后使 \(1-n\) 最短路径增加的最大增量. Sol Dijstra. 先跑一边最短路,然后枚举最短路,将路径翻倍然后跑Dijstra... 因为不在最短路径上的边没用贡献,然后最短路径最长为 \(n-1\) 复杂度 \(O(nmlogm\) Code /************************************************************** Problem: 3445