纪中OJ 5177【NOIP2017提高组模拟6.28】Trevel

动态SPFA水题,和之前某道魔法森林相似

我们先存边,然后按L排个序,之后在将每一条边加入,每加入一条边,就以当前边的两个端点为起点,做一次双源最短路,不难发现,加入这条边后,这两个点最可能更新其他点

初始化时除了1之外,其他点的dis=0,dis[1]=inf,然后我们按照R来做最长路,考虑点u,v,边 e,dis[v]可能的取值有三种,v之前被更新过,所以有一个dis[v],考虑题目的限制,这次路线的的区间是最大的L~最小的R,因为我们按照L从小到达排序,所以图中最大的L就是刚刚加入的边,所以不需要考虑L,那么考虑R,在到达u之前,可能存在一条边p是到达u必须要走的边且是必须边中最小的(自己感性理解,必须边是一条链,那么必须要走这条最小的边,那么R只能是这条边的R),val[p]val[e],那么在这条边之前没有比这条边R小的,但这条边又是u->v的必须边,所以dis[v]只能等于val[e],所以我们得到在跑SPFA时,更新条件为

if (dis[v]>min(dis[u],val[e])) dis[v]>min(dis[u],val[e]);

然后记录SPFA中max(dis[n]-SPFA前加入的边的L)

代码

//By AcerMo
#include
#include
#include
#include
#include
#include
using namespace std;
const int M=5050;
struct edge
{
	int x,y,w1,w2;
	bool friend operator < (edge a,edge b)
	{
		return a.w1q;
inline int read()
{
	int x=0;char ch=getchar();
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}
inline void add(int x,int y,int w,int c)
{
	to[++cnt]=y;nxt[cnt]=head[x];co1[cnt]=w;co2[cnt]=c;head[x]=cnt;
	to[++cnt]=x;nxt[cnt]=head[y];co1[cnt]=w;co2[cnt]=c;head[y]=cnt;
	return ;
}
inline void SPFA(int st,int ed)
{
	q.push(st);q.push(ed);
	while (q.size())
	{
		int u=q.front();q.pop();vis[u]=0;
		for (int i=head[u];i;i=nxt[i])
		{
			if (dis[to[i]]

 

你可能感兴趣的:(图论-最短路)