【次短路径/SPFA】BZOJ1726-[Usaco2006 Nov]Roadblocks第二短路

时间:2023-03-09 09:07:44
【次短路径/SPFA】BZOJ1726-[Usaco2006 Nov]Roadblocks第二短路

【题目大意】

求无向图点1到n的次短路。

【思路】

一年多前写过一次堆优化Dijkstra的,方法就是一边跑Dijsktra一边就把次短路径保存下来。和一般Dijkstra不同的是把vis数组去掉了,因为还要生成次短路径。戳这里

今天重新写用的是SPFA。正反跑两次SPFA,然后枚举每一条边,如果起点到一个端点的最短路+另一个端点到终点的最短路+长度 ≠ 最短路,则和答案比较,保存最小值。还是很好理解的:D

 #include<bits/stdc++.h>
using namespace std;
const int MAXR=+;
const int MAXN=+;
const int INF=0x7fffffff;
struct edge
{
int to;
int len;
};
vector<edge> E[MAXN];
int n,r,dis[MAXN],inque[MAXN],dis1[MAXN],dis2[MAXN];
int u[MAXR],v[MAXR],w[MAXR]; void addedge(int u,int v,int w)
{
E[u].push_back((edge){v,w});
E[v].push_back((edge){u,w});
} void init()
{
scanf("%d%d",&n,&r);
for (int i=;i<=r;i++)
{
scanf("%d%d%d",&u[i],&v[i],&w[i]);
addedge(u[i],v[i],w[i]);
}
} void spfa(int S,int T)
{
for (int i=;i<=n;i++) inque[i]=,dis[i]=INF;
queue<int> que;
que.push(S);
inque[S]=;dis[S]=;
while (!que.empty())
{
int head=que.front();que.pop();
inque[head]=;
for (int i=;i<E[head].size();i++)
{
int nowdis=dis[head]+E[head][i].len,to=E[head][i].to;
if (nowdis<dis[to])
{
dis[to]=nowdis;
if (!inque[to])
{
que.push(to);
inque[to]=;
}
}
}
}
} void solve()
{
spfa(,n);
for (int i=;i<=n;i++) dis1[i]=dis[i];
spfa(n,);
for (int i=;i<=n;i++) dis2 [i]=dis[i];
int mx=dis1[n],ans=INF;
for (int i=;i<=r;i++)
{
int now=dis1[u[i]]+dis2[v[i]]+w[i];
if (now!=mx) ans=min(ans,now);
now=dis1[v[i]]+dis2[u[i]]+w[i];
if (now!=mx) ans=min(ans,now);
}
printf("%d",ans);
} int main()
{
init();
solve();
return ;
}