题目:我是超链接
题意:求1-n的次短路
题解:
A∗算法可以用来求第k短路,当然也可以用来求次短路。
此题也可以直接用求次短路的方法(在Dijkstra上进行少许修改)解决。到某个顶点v的次短路要么是到其他某个顶点u的最短路再加上u→v的边,要么是到u的次短路再加上u→v的边。对于每个顶点,我们记录的不仅仅是最短距离,还有次短距离。在跑Dijkstra时,不断更新这两个距离即可。
代码:
#include<cstdio>
#include<cstring>
#include<queue>
#define M 200005
#define N 100005
#define LL long long
using namespace std;
const LL INF=1e18;
LL dis[N],dis2[N];//次短距离
int point[N],tot,nxt[M],v[M],c[M];
void addedge(int x,int y,int t){++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=t;}
struct hh{LL f;int i;bool operator <(const hh &a)const{return a.f<f;}};
void Dij(int t,int s)//点的编号从1开始
{
for(int i=0;i<=t;i++) dis[i]=INF,dis2[i]=INF;
priority_queue<hh> q;
dis[s]=0;
q.push((hh){0,s});
while(!q.empty())
{
hh now=q.top(); q.pop();
int u=now.i;
LL d=now.f;
if(dis2[u]<d) continue;
for(int i=point[u];i;i=nxt[i])
{
LL d2=d+c[i];
if(dis[v[i]]>d2)
{
dis2[v[i]]=dis[v[i]];
dis[v[i]]=d2;
q.push((hh){dis[v[i]],v[i]});
}
else
if(dis2[v[i]]>d2)
{
dis2[v[i]]=d2;
q.push((hh){dis2[v[i]],v[i]});
}
}
}
}
int main()
{
int T,u,v,w,n,m,s,t;
scanf("%d",&T);
while(T--)
{
tot=0; memset(point,0,sizeof(point));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);addedge(v,u,w);
}
Dij(n,1);
printf("%lld\n",dis2[n]);
}
}