求第k最短路
这里要说的就比较多了,朴素的方法有两种实现的办法
1:spfa求,当把所有顶点的前k临时最短路都求出时,前k临时最短路就是确切的最短路,因为第k+1短路不能更新第k以内的最短路
2:dijkstra求,用宽搜实现该算法,第k次搜该顶点时,即为该顶点的第k最短路,因为是宽搜,所以保证后边的所有路径都比它长,因此该算法的正确性得到保证
但是前边两种做法都会tle
3:
网上流传的做法,启发式搜索
做反图,求最短路
然后f(n)=h(n)+g(n),反图的最短路就是g(n)
启发式搜索相比较于普通的宽搜的优点在于,有了估价函数的帮助,它会朝着目标搜索,而不是盲目的搜索
但是这样第一次搜索到的解怎么保证它是最优的呢?
首先,g(n)一定要小于等于离目标点的距离,那么当目标顶点出队列的时候,由于其他路径的更佳值都比该点的确切值差,那么他们的确切值最不可能超过它
至于启发式搜索的效率,这个不是那么好估计,等待以后弄明白了再补上
再啰嗦两句:关于堆的问题,这次是手写的堆,不过不得不说这个还是有点麻烦的,一来增加的了错误的可能性
,二来,这个有两个adjust函数,写起来也是要一点时间的
错误的地方:dijkstra写错了,起点更新的时候是直接更新的,这样对于起点自环会出错
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
int n,m;
struct node
{
int to,dis;
struct node *next;
}a[10010];
struct gt
{
int to,dis;
struct gt *next;
}b[10010];
struct node *p;
struct gt *q;
int d[10001],txt[10001];
int time[10001];
int dijs(int t,int n)
{
for(int i=1;i<=n;i++)
d[i]=inf;
d[t]=0;
for(int i=2;i<=n;i++)
{
int ted=inf,tmp=n+1;
for(int j=1;j<=n;j++)
{
if(ted>d[j]&&txt[j]==0)
{
ted=d[j];
tmp=j;
}
}
if(tmp==n+1) return(0);
txt[tmp]=1;
p=a[tmp].next;
while(p!=&a[tmp])
{
if(d[p->to]>d[tmp]+p->dis)
d[p->to]=d[tmp]+p->dis;
p=p->next;
}
}
return(0);
}
int front,end;
struct
{
short node;
int dis;
}queue[20000001];
int swap(int t,int s)
{
int tmp=queue[t].node,dis=queue[t].dis;
queue[t].node=queue[s].node,queue[t].dis=queue[s].dis;
queue[s].node=tmp,queue[s].dis=dis;
return(0);
}
int adjust1(int t,int n)
{
int i=t,j;
while(i*2<=n)
{
j=i*2;
if(j+1<=n&&queue[j].dis+d[queue[j].node]>queue[j+1].dis+d[queue[j+1].node]) j++;
if(queue[j].dis+d[queue[j].node]>=queue[i].dis+d[queue[i].node]) break;
swap(i,j);
i=j;
}
return(0);
}
int adjust2(int n)
{
int i=n,j;
while(i/2>=1)
{
j=i/2;
if(queue[i].dis+d[queue[i].node]>=queue[j].dis+d[queue[j].node]) break;
swap(i,j);
i=j;
}
return(0);
}
int solve(int s,int k)
{
// printf("%d\n",time[s]);
int t=queue[front].node;
int dis=queue[front].dis;
// printf("%d\n",t);
swap(1,end);
adjust1(1,--end);
// ++time[t];
if(++time[t]>k) return(0);
if(time[s]==k)
{
printf("%d\n",dis);
return(0);
}
q=b[t].next;
while(q!=&b[t])
{
queue[++end].node=q->to;
queue[end].dis=dis+q->dis;
adjust2(end);
q=q->next;
}
}
int main()
{
freopen("in.txt","r",stdin);
while(scanf("%d %d",&n,&m)!=EOF)
{
// printf("hi");
for(int i=1;i<=n;i++)
{
a[i].next=&a[i];
b[i].next=&b[i];
}
// printf("hi");
for(int i=1;i<=m;i++)
{
int from,to,dis;
scanf("%d %d %d",&to,&from,&dis);
p=(struct node*)malloc(sizeof(struct node));
p->next=a[from].next;
a[from].next=p;
p->dis=dis;
p->to=to;
q=(struct gt*)malloc(sizeof(struct gt));
q->next=b[to].next;
b[to].next=q;
q->dis=dis;
q->to=from;
}
int t,s,k;
scanf("%d %d %d",&t,&s,&k);
memset(txt,0,sizeof(txt));
dijs(s,n);
front=1;
end=1;
queue[front].node=t;
queue[front].dis=0;
if(t==s) k++;
memset(time,0,sizeof(time));
while(front<=end&&time[s]<k)
{
// printf("%d\n",limit[s]);
solve(s,k);
}
if(time[s]<k)
printf("-1\n");
}
// int sum=0;
// for(int i=1;i<=n;i++)
// sum+=d[i];
// printf("%d\n",sum);
// printf("%d\n",end);
return 0;
}