这个题就是严格次短路问题,边是无向边,这里记下三种做法,一是直接dijkstra求,二是dijkstra+A*求,三是两次最短路。
dijkstra:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
dijkstra+A*:
这里先讲一下思路。首先用dijkstra处理出从n到每个点的最短距离,然后调用A*算法,从1开始处理,每次把相邻的点的边权加上,再存进队列,这样每次存进去的就是1到每个点的距离,然后根据这个距离+当前点到n的最短距离排序。那么第一次n点取出来时就是1到n的最短路,然后继续加相邻边权放入队列,那么第二次处理到n,就是最短路加上一条除了最短路经过的边以外的一条最短边的值,也就是次短距离了。
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=5000+10;
int n,m,u,v,val;
int dis[maxn];
struct P
{
int to,cost;
bool operator < (const P & a) const
{
return cost>a.cost;
}
};
vector edge[maxn];
void Dijkstra()
{
fill(dis,dis+n+2,INF);
dis[n]=0;
priority_queue
qu;
qu.push(P{n,0});
while(!qu.empty())
{
P x=qu.top();
qu.pop();
for(int i=0;idis[x.to]+y.cost)
{
dis[y.to]=dis[x.to]+y.cost;
qu.push(P{y.to,dis[y.to]});
}
}
}
}
struct node
{
int to,len;
bool operator < (const node & a) const
{
return len+dis[to]>a.len+dis[a.to];
}
};
int A_star()
{//if(dis[1]==INF) return -1;当不存在最短路时要加上,不然会死循环。
priority_queue qu;
qu.push(node{1,0});
int num=0;
while(!qu.empty())//这个地方有点搜索的味道,从1开始不断加上相邻的点的边权,然后放入队列。就是从1开始不断向n拓展
{
node a=qu.top();
qu.pop();
if(a.to==n) num++;
if(num==2) return a.len;
for(int i=0;i
两次最短:
从起点跑一次最短路,然后再从终点跑一次最短路,然后遍历一遍所有的边,次短路的距离就是其中某条边的权值加上起点到一个点的最短路加上终点到另一个点的最短路
#include
#include
#include
#include
#include
#include
#pragma GCC optimize(2)
#define INF 0x3f3f3f3f
using namespace std;
const int N=5000+5;
int n,m,u,v,val;
struct P
{
int to,cost;
};
vector > G;//刚学的二维vector使用,使用前需要resize其大小
int dis1[N],dis2[N],vis[N];
void spfa(int s,int *dis)
{
memset(vis,0,sizeof(vis));
dis[s]=0;
queue qu;
qu.push(s);
while(!qu.empty()){
int U=qu.front();
qu.pop();
vis[U]=0;
for(int i=0;idis[U]+V.cost){
dis[V.to]=dis[U]+V.cost;
if(!vis[V.to]){
vis[V.to]=1;
qu.push(V.to);
}
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF){
G.resize(n+1); G.clear();
memset(dis1,INF,sizeof(dis1));
memset(dis2,INF,sizeof(dis2));
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&val);
G[u].push_back(P{v,val});
G[v].push_back(P{u,val});
}
spfa(1,dis1);
spfa(n,dis2);
int ans=INF;
for(int i=1;i<=n;i++){//遍历所有的边
for(int j=0;jdis1[n] && temp