poj 2449 第k短路
题目链接:http://poj.org/problem?id=2449
注意事项:
1.跑完spfa发现起点到终点无法到达时,直接返回函数
2.反向建边跑完spfa以后,一定要清空cnt和fist数组,nxt数组,以防乱掉
3.特判:起点等于终点时,最短路0不算作题目里面的最短路,因此,问题转化为求第k+1短路,也就是K++或k–
※※4.如果开数组记录每个点的g,那么每次pop出来的点,不能记录它入堆时的g,会求出错误答案,因此堆中加入的元素,每一次都要记录g和h,防止g数组被后来的该点的其他g值覆盖,求出错误答案(我一开始就是wa在了这里)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
queue<int>q;
const int maxn=1000+10;
int N,M,S,T,K,cnt=0,k=0,ans,last,tot=0;
int fist[maxn],nxt[maxn*200],h[maxn];
bool vis[maxn];
struct hh
{
int f,t,v;
}e[maxn*100];
struct lxt
{
int g,h,num;
};
priority_queue<lxt>que;
bool operator < (lxt x,lxt y)
{
return x.g+x.h>y.g+y.h;
}
void init()
{
while(!q.empty()) q.pop();
while(!que.empty()) que.pop();
memset(h,0x7f,sizeof(h));
memset(fist,-1,sizeof(fist));
memset(nxt,0,sizeof(nxt));
memset(vis,0,sizeof(vis));
memset(e,0,sizeof(e));
cnt=tot=k=0;
}
void build(int f,int t,int v)
{
e[++cnt].f=f;
e[cnt].t=t;
e[cnt].v=v;
nxt[cnt]=fist[f];
fist[f]=cnt;
}
void A_star()
{
if(S==T) K++;
if(h[S]==h[0])
{
ans=-1;
return;
}
lxt start;
start.num=S;
start.h=h[S];
start.g=0;
que.push(start);
while(!que.empty())
{
lxt u=que.top();
que.pop();
if(T==u.num)
{
k++;
if(k==K)
{
ans=u.g+u.h;
return;
}
}
for(int i=fist[u.num];i!=-1;i=nxt[i])
{
int v=e[i].t;
lxt f;
f.num=v;
f.g=u.g+e[i].v;
f.h=h[v];
que.push(f);
}
}
ans=-1;
}
void spfa()
{
vis[T]=1;
h[T]=0;
q.push(T);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=fist[u];i!=-1;i=nxt[i])
{
int v=e[i].t;
if(h[v]>h[u]+e[i].v)
{
h[v]=h[u]+e[i].v;
if(!vis[v])
{
q.push(v);
vis[v]=1;
}
}
}
vis[u]=0;
}
}
int main()
{
while(scanf("%d%d",&N,&M)!=EOF)
{
init();
for(int i=1;i<=M;++i)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
build(b,a,c);
}
scanf("%d%d%d",&S,&T,&K);
spfa();
cnt=0;
memset(fist,-1,sizeof(fist));
memset(nxt,0,sizeof(nxt));
for(int i=1;i<=M;++i)
build(e[i].t,e[i].f,e[i].v);
A_star();
printf("%d\n",ans);
return 0;
}
}