题目链接:http://poj.org/problem?id=2449
题意:
给定一个有向图,
寻找有向第K短路。
算法:
我用的是A*算法。
f[x]=g[x]+h[x]。
其中g[x]是由起点到当前节点的距离
h[x]是当前节点到终点的最短距离。
本题的边是单向的,
但是在反向SPFA处理h[x]的时候要用到反向边。
trick:
s等于t的时候,不能直接认为0是最短路。
代码如下:
#include<cstdio> #include<iostream> #include<algorithm> #include<sstream> #include<cstdlib> #include<cstring> #include<string> #include<climits> #include<cmath> #include<queue> #include<vector> #include<stack> #include<set> #include<map> #define INF 0x3f3f3f3f #define eps 1e-8 using namespace std; typedef pair<int,int> PII; int E; const int MAXN=1010,MAXM=200010; int to[MAXM],w[MAXM],nxt[MAXM],head[MAXN]; int d[MAXN],cnt[MAXN]; int Q[MAXN]; bool inq[MAXN]; priority_queue <pair<PII,int> > q; void _addedge(int u, int v, int val) { to[E]=v; w[E]=val; nxt[E]=head[u]; head[u]=E++; } void addedge(int u, int v, int val) { _addedge(u,v,val); _addedge(v,u,val); } void spfa(int s, int t) { d[t]=0; int front=0,rear=0; Q[rear++]=t; while(front!=rear) { int u=Q[front++]; front%=MAXN; inq[u]=false; for(int i=head[u]; i!=-1; i=nxt[i]) { if(i&1) { int v=to[i]; if(d[v]>d[u]+w[i]) { d[v]=d[u]+w[i]; if(inq[v]) { continue; } Q[rear++]=v; rear%=MAXN; inq[v]=true; } } } } } int astar(int s, int t, int k) { while(!q.empty()) { q.pop(); } q.push(make_pair(make_pair(-d[s],0),s)); while(!q.empty()) { int dist=-q.top().first.first; int val=q.top().first.second; int u=q.top().second; q.pop(); cnt[u]++; if(cnt[u]>k) { continue; } if(cnt[t]==k) { return dist; } for(int i=head[u]; i!=-1; i=nxt[i]) { if(i&1) { continue; } int v=to[i]; q.push(make_pair(make_pair(-(val+w[i]+d[v]),val+w[i]),v)); } } return -1; } int main() { int n,m; while(scanf("%d%d",&n,&m)==2) { E=0; memset(head,-1,sizeof(head)); memset(d,INF,sizeof(d)); memset(cnt,0,sizeof(cnt)); memset(inq,0,sizeof(inq)); while(m--) { int u,v,val; scanf("%d%d%d",&u,&v,&val); addedge(u,v,val); } int s,t,k; scanf("%d%d%d",&s,&t,&k); spfa(s,t); if(s==t) { k++; } printf("%d\n",astar(s,t,k)); } return 0; }