昨晚看WC论文发现自己连K短路的经典A*算法还不会,补了一波,模板题输出-1后没return继续跑wa了一早上......
算法流程:
①在反向图中求出t到每个点的最短路
②从原点bfs,估价f=d+dis[x],即当前已走的路径长度+最短路径
③遇到第k次汇点就是答案
据说这复杂度是O(n*k)的....不会证.....
代码:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define inf 1<<29
#define M 500200
#define N 500020
using namespace std;
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int n,m,k,s,t;
int head[N],pos;
int head1[N],pos1;
struct edge{int to,c,next;}ee[M<<1],e[M<<1];
void add(int a,int b,int c)
{pos++;e[pos].to=b,e[pos].c=c,e[pos].next=head[a],head[a]=pos;}
void add1(int b,int a,int c)
{pos1++;ee[pos1].to=b,ee[pos1].c=c,ee[pos1].next=head1[a],head1[a]=pos1;}
queue<int>Q;bool vis[N];int dis[N];
void spfa(int st)
{for(int i=1;i<=n;i++)dis[i]=inf,vis[i]=0;dis[st]=0,vis[st]=1;Q.push(st);while(!Q.empty()){int u=Q.front();Q.pop();vis[u]=0;for(int i=head1[u];i;i=ee[i].next){int v=ee[i].to;if(dis[v]>dis[u]+ee[i].c){dis[v]=dis[u]+ee[i].c;if(!vis[v])Q.push(v),vis[v]=1;}}}
}
struct node{int x,d,f;}u,v;
bool operator < (node a,node b)
{if(a.f!=b.f)return a.f>b.f;
}
priority_queue<node>que;
void solve()
{while(!que.empty())que.pop();if(dis[s]==inf){printf("-1\n"); return ;}u.f=dis[s],u.x=s,u.d=0;int now=0;que.push(u);while(!que.empty()){u=que.top();que.pop();if(u.x==t)now++;if(now==k){printf("%d\n",u.d);return;}for(int i=head[u.x];i;i=e[i].next){int tc=e[i].to;v=u;v.x=tc,v.d+=e[i].c;v.f=dis[v.x]+v.d;que.push(v);}}printf("-1\n");
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);while(~scanf("%d%d",&n,&m)){memset(head,0,sizeof(head));memset(head1,0,sizeof(head1));pos1=pos=0;for(int i=1;i<=m;i++){int x=read(),y=read();int c=read();add(x,y,c);add1(x,y,c);}s=read(),t=read(),k=read();if(s==t)k++;spfa(t);solve();}
}