题意
给出一个无向图,求出次短路径(一条路可以来回走)。
思路
跑两边SPFA,一次从起点跑,一次从终点跑。然后枚举一条中转边,找到比最短路长的路径,取最小值。
代码
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
int n,r,a[100001],b[100001],c[100001],head[10001],tot,d1[10001],d2[10001],v[10001],ans;
struct node{
int x,y,next,v;
}e[200001];
inline void add(int x,int y,int w)
{
e[++tot].y=y;e[tot].next=head[x];e[tot].v=w;head[x]=tot;
e[++tot].y=x;e[tot].next=head[y];e[tot].v=w;head[y]=tot;
}
inline void SPFA1()
{
queue<int> q;
int x,y;
memset(d1,127/3,sizeof(d1));
v[1]=1;d1[1]=0;q.push(1);
while (q.size())
{
x=q.front();q.pop();v[x]=0;
for (int i=head[x];i;i=e[i].next)
{
y=e[i].y;
if (d1[y]>d1[x]+e[i].v)
{
d1[y]=d1[x]+e[i].v;
if (!v[y])
{
v[y]=1;
q.push(y);
}
}
}
}
}
inline void SPFA2()
{
queue<int> q;
int x,y;
memset(d2,127/3,sizeof(d2));
memset(v,0,sizeof(v));
v[n]=1;d2[n]=0;q.push(n);
while (q.size())
{
x=q.front();q.pop();v[x]=0;
for (int i=head[x];i;i=e[i].next)
{
y=e[i].y;
if (d2[y]>d2[x]+e[i].v)
{
d2[y]=d2[x]+e[i].v;
if (!v[y])
{
v[y]=1;
q.push(y);
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&r);
for (int i=1;i<=r;i++)
{
scanf("%d%d%d",&a[i],&b[i],&c[i]);
add(a[i],b[i],c[i]);
}
SPFA1();
SPFA2();
int x,y;
ans=1e9;
for (int i=1;i<=r;i++)//找次短路径
{
if (d1[b[i]]+d2[a[i]]+c[i]>d1[n]) ans=min(ans,d1[b[i]]+d2[a[i]]+c[i]);
if (d1[a[i]]+d2[b[i]]+c[i]>d1[n]) ans=min(ans,d1[a[i]]+d2[b[i]]+c[i]);//这可以画图理解一下
}
printf("%d",ans);
}