第二短路

Posted tyouchie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第二短路相关的知识,希望对你有一定的参考价值。

oj1220

贝茜把家搬到了一个小农场,但她常常回到FJ的农场去拜访她的朋友。贝茜很喜欢路边的风景,不想那么快地结束她的旅途,于是她每次回农场,都会选择第二短的路径,而不象我们所习惯的那样,选择最短路。

贝茜所在的乡村有R(1<=R<=100,000)条双向道路,每条路都联结了所有的N(1<=N<=5000)个农场中的某两个。贝茜居住在农场1,她的朋友们居住在农场N(即贝茜每次旅行的目的地)。

贝茜选择的第二短的路径中,可以包含任何一条在最短路中出现的道路,并且,一条路可以重复走多次。当然咯,第二短路的长度必须严格大于最短路(可能有多条)的长度,但它的长度必须不大于所有除最短路外的路径的长度。

第二短路顾名思义要比第一短路要长,必剩余其他路短,所以比较是肯定要比较两次的啦,那么对于第二短路我们也要让它尽可能的短,所以我们用第一短路来寻找第二短路;

所以我们开两个数组,dis1,dis2,分别表示第一短路和第二短路;

所以

if(dis1[v]>dis1[x]+a[i].v)
{
dis2[v]=dis1[v];


dis1[v]=dis1[x]+a[i].v;
if(!vis[v]) vis[v]=1,q.push(v);
}
else if(dis1[x]+a[i].v<dis2[v]&&dis1[x]+a[i].v>dis1[v])
{//寻找满足条件的第二短路,二个条件是为了满足能够更新dis2(因为只有满足小于除最短路外的所有路)
dis2[v]=dis1[x]+a[i].v;
if(!vis[v]) q.push(v),vis[v]=1;
}
if(dis2[x]+a[i].v<dis2[v])
{//第二短路也需要找到最短路,比较更新;
dis2[v]=dis2[x]+a[i].v;
if(!vis[v]) q.push(v),vis[v]=1;

}

这样不断更新第二短路,就找到我们想要的answer啦;

代码

技术分享图片
#include<bits/stdc++.h>
using namespace std;
#define N 5010
#define M 100010
int n,lin[N],tot,vis[N],dis1[N],xx,yy,vv,m,dis2[N];
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch))    {if(ch==-) f=-1;ch=getchar();}
    while(isdigit(ch))    {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
struct gg
{
    int y,next,v;
}a[M<<1];
inline void init(int xx,int yy,int vv)
{
    a[++tot].y=yy;
    a[tot].next=lin[xx];
    a[tot].v=vv;
    lin[xx]=tot;
}
inline void spfa()
{
    queue<int> q;
    memset(vis,0,sizeof(vis));
    memset(dis1,127,sizeof(dis1));
    memset(dis2,127,sizeof(dis2));
    dis1[1]=0;vis[1]=1;q.push(1);
    while(!q.empty())
    {
        int x=q.front();q.pop();vis[x]=0;
        for(int i=lin[x];i;i=a[i].next)
        {
            int v=a[i].y;
            if(dis1[v]>dis1[x]+a[i].v) 
            {
                dis2[v]=dis1[v];
                dis1[v]=dis1[x]+a[i].v;
                if(!vis[v]) vis[v]=1,q.push(v);
            }
            else if(dis1[x]+a[i].v<dis2[v]&&dis1[x]+a[i].v>dis1[v])
            {
                dis2[v]=dis1[x]+a[i].v;
                if(!vis[v]) q.push(v),vis[v]=1;
            }
            if(dis2[x]+a[i].v<dis2[v])
            { 
                dis2[v]=dis2[x]+a[i].v;
                if(!vis[v]) q.push(v),vis[v]=1;
            }
        }    
    }
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=m;i++)
    {
        xx=read();yy=read();vv=read();
        init(xx,yy,vv);
        init(yy,xx,vv);
    }
    spfa();
    cout<<dis2[n]<<endl; 
    return 0;
}
View Code

 



















以上是关于第二短路的主要内容,如果未能解决你的问题,请参考以下文章

分享几个实用的代码片段(第二弹)

list(), if 和短路评估

[SPFA][jzyzoj1220]第二短路

第二次在对话框中膨胀片段时出错

(47)C#里使用短路操作符

(47)C#里使用短路操作符