这就是裸的k短路了
学习一发A*的姿势:http://yzmduncan.iteye.com/blog/1162759
这个S==T的坑要注意
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<queue>
#define V G[p].v
using namespace std;
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x)
{
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int M=200005;
const int N=1005;
struct edge{
int u,v,w;
int next;
};
int head[N],inum;
edge G[M];
inline void add(int u,int v,int w,int p){
G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p;
}
int iu[M],iv[M],iw[M];
int n,m,S,T,K;
int dis[N],flag[N],Map[N][N];
inline void Dij(int S)
{
memset(dis,0x3f,sizeof(dis));
dis[S]=0;
for (int i=1;i<n;i++)
{
int k=0;
for (int j=1;j<=n;j++)
if (!flag[j] && (!k || dis[j]<dis[k]))
k=j;
flag[k]=1;
for (int j=1;j<=n;j++)
if (!flag[j] && dis[j]>dis[k]+Map[k][j])
dis[j]=dis[k]+Map[k][j];
}
}
struct abcd{
int u,g,f;
abcd(int u=0,int g=0,int f=0):u(u),g(g),f(f) { }
bool operator < (const abcd &B) const {
return f>B.f;
}
};
int cnt[N];
inline int A_star()
{
priority_queue<abcd> Q; abcd now;
if (dis[S]==0x3f3f3f3f) return -1;
Q.push(abcd(S,0,dis[S]));
while (!Q.empty())
{
now=Q.top(); Q.pop();
cnt[now.u]++;
if (cnt[T]==K) return now.f;
if (cnt[now.u]>K) continue;
for (int p=head[now.u];p;p=G[p].next)
Q.push(abcd(V,now.g+G[p].w,now.g+G[p].w+dis[V]));
}
return -1;
}
int main()
{
int iu,iv,iw;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m);
memset(Map,0x3f,sizeof(Map));
for (int i=1;i<=n;i++) Map[i][i]=0;
for (int i=1;i<=m;i++)
read(iu),read(iv),read(iw),add(iu,iv,iw,++inum),Map[iv][iu]=min(Map[iv][iu],iw);
read(S); read(T); read(K);
Dij(T);
if (S==T) K++;
printf("%d\n",A_star());
return 0;
}
UPD:可持久化堆维护 详见另一篇博文
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#define cl(x) memset(x,0,sizeof(x));
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int M=100005;
const int N=10005;
struct edge{
int u,v,next; ll w;
}G[M];
int head[N],inum=1;
inline void add(int u,int v,ll w,int p){
G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p;
}
#define V G[p].v
#define U G[p].u
namespace DIJ{
#define val(x) dis[H[x]]
#define K(x) (x<<1|1)>cnt?(x<<1):(val(x<<1)<val(x<<1|1)?(x<<1):(x<<1|1))
ll* dis;
int H[N];
int cnt,back[N],vst[N];
inline void Swp(int x,int y){
swap(H[x],H[y]); swap(back[H[x]],back[H[y]]);
}
inline void Up(int x){
for (;x && val(x)<val(x>>1);x>>=1) Swp(x,x>>1);
}
inline void Down(int x){
for (int tmp;(x<<1)<=cnt && val(x)>val(tmp=K(x));x=tmp) Swp(x,tmp);
}
inline void Dij(int S,int n,ll *dis){
int u; DIJ::dis=dis;
cnt=0; H[++cnt]=S; back[S]=cnt; dis[S]=0; vst[S]=1;
for (int i=1;i<=n;i++)
if (i!=S)
H[++cnt]=i,back[i]=cnt,dis[i]=1<<30,vst[i]=0;
for (int i=1;i<n;i++){
u=H[1]; vst[H[1]]=1;
Swp(1,cnt--); Down(1);
for (int p=head[u];p;p=G[p].next)
if (!vst[V] && dis[V]>dis[U]+G[p].w){
dis[V]=dis[U]+G[p].w;
Up(back[V]);
}
}
}
}
inline int ran(){
static int x=31253125; x+=(x<<4)+1; return x&65536;
}
struct node{
node *l,*r; int p;
bool operator < (const node &B) const{
return G[p].w<G[B.p].w;
}
}nodes[(N+M)*30],*root[N];
int ncnt,rcnt;
inline node *Me(node *A,node *B){
node *ret=nodes+(++ncnt);
if (!A || !B) { *ret=A?*A:*B; return ret; }
if (*B<*A) swap(A,B);
*ret=*A; ran()?ret->l=Me(A->l,B):ret->r=Me(A->r,B);
return ret;
}
int S,T;
int n,m,K;
int ru[M],rv[M],rw[M];
ll dis[N]; int vst[N],nxt[N];
int tag[M];
int lst[N],pnt;
inline void dfs(int u){
vst[u]=1; lst[++pnt]=u;
for (int p=head[u];p;p=G[p].next)
if (!vst[V] && dis[V]==dis[u]+G[p].w)
tag[p]=1,nxt[V]=u,dfs(V);
}
inline void Build(){
for (int i=1;i<=pnt;i++){
int u=lst[i];
node *last=root[nxt[u]];
for (int p=head[u];p;p=G[p].next)
if (!tag[p] && dis[V]!=1<<30){
++ncnt; nodes[ncnt].p=p;
last=Me(last,nodes+ncnt);
}
root[u]=last;
}
}
struct abcd{
ll val; node *last;
abcd(ll v,node *l) { val=v; last=l; }
bool operator < (const abcd &B) const{
return val>B.val;
}
};
priority_queue<abcd> Q;
ll Ans=-1;
inline void Solve(){
Q.push(abcd(dis[S],NULL));
for (int i=1;i<=K && !Q.empty();i++){
abcd t=Q.top(); Q.pop();
if (i==K) { Ans=t.val; break; }
int v=t.last?G[t.last->p].v:S;
if (t.last){
if (t.last->l)
Q.push(abcd(t.val-G[t.last->p].w+G[t.last->l->p].w,t.last->l));
if (t.last->r)
Q.push(abcd(t.val-G[t.last->p].w+G[t.last->r->p].w,t.last->r));
}
if (root[v])
Q.push(abcd(t.val+G[root[v]->p].w,root[v]));
}
}
int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m);
for (int i=1;i<=m;i++) read(ru[i]),read(rv[i]),read(rw[i]),add(rv[i],ru[i],rw[i],++inum);
read(S); read(T); read(K); if (S==T) K++;
DIJ::Dij(T,n,dis);
dfs(T);
cl(head); inum=1;
for (int i=1;i<=m;i++) add(ru[i],rv[i],dis[rv[i]]+rw[i]-dis[ru[i]],++inum);
Build();
Solve();
printf("%lld\n",Ans);
return 0;
}