Time Limit: 4000MS | Memory Limit: 65536K | |
Total Submissions: 19030 | Accepted: 5199 |
Description
"Prince Remmarguts lives in his kingdom UDF – United Delta of Freedom. One day their neighboring country sent them Princess Uyuw on a diplomatic mission."
"Erenow, the princess sent Remmarguts a letter, informing him that she would come to the hall and hold commercial talks with UDF if and only if the prince go and meet her via the K-th shortest path. (in fact, Uyuw does not want to come at all)"
Being interested in the trade development and such a lovely girl, Prince Remmarguts really became enamored. He needs you - the prime minister's help!
DETAILS: UDF's capital consists of N stations. The hall is numbered S, while the station numbered T denotes prince' current place. M muddy directed sideways connect some of the stations. Remmarguts' path to welcome the princess might include the same station twice or more than twice, even it is the station with number S or T. Different paths with same length will be considered disparate.
Input
The last line consists of three integer numbers S, T and K (1 <= S, T <= N, 1 <= K <= 1000).
Output
Sample Input
2 2 1 2 5 2 1 4 1 2 2
Sample Output
14
【题目大意】:
给定一个图,求起点到终点的第k短路
【分析】:
由启发式A*算法的基本更新式F(x)=G(x)+H(x)<其中G(x)表示从起点到当前点实际走过的路程,H(x)表示从当前点到终点的预估值>。
1):考虑对h(x)进行设计,根据定义H(x)为当前点x到终点所需要的实际距离。也就是说x->终点的距离,为了计算这个估计值,我们算出x->终点的最短路径长度。显然对于x点的值很多而终点的值只有一个,于是我们反过来做,从终点出发到其他点的单源点最短路径,这里求最短路的图用的是原有向图的反图,这样求出的才是x->终点的最短路。
2):如何求出第K短路,维护数组num[x]表示从起始点到x点已经找到了第num[x]短路,那么做法为:从初始点向外拓展,同时将此时的num[x]加上1<表示此时已经找到了初始点到达该点的第num[x]短路>,将其能到达的点全部加入堆,堆的维护规则为:堆顶总是为“初始点到该点距离+该点到终点的预估值”最小的一个点。
注意每次向堆中加入一点时应更新其“初始点到该点距离”和“该点到终点的预估值”,当num[终点]的值等于K时,说明找到第K短路,当num[当前点]的值大于K时,不再由该点更新,因为该点已找到第z短路,z>K
【代码】:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define MAXN 1001
#define MAXM 200101
#define MAXQ 10001
#define IMAX 21474836
struct EDGE{int t,v,next;};
struct STATE
{
int real,est,node;
/*friend bool operator <(STATE X,STATE Y)
{
return X.real+X.est<Y.real+Y.est;
}*/
bool operator <(STATE X)const
{
return X.real+X.est<real+est;
}
};
EDGE a[MAXM];
int N,M,S,T,K,last[MAXN],tail[MAXN],num[MAXN],ans=0,tot=0;
int H[MAXN];
int Q[MAXQ];
bool vis[MAXN];
void add(int from,int to,int value)
{
a[++tot].t=to;
a[tot].v=value;
a[tot].next=last[from];
last[from]=tot;
a[++tot].t=from;
a[tot].v=value;
a[tot].next=tail[to];
tail[to]=tot;
}
void pre_spfa()
{
int right=1,left=1;
for(int i=1;i<=N;i++)
H[i]=IMAX;
memset(vis,false,sizeof(vis));
H[T]=0;
vis[T]=true;
Q[right]=T;
//while(left!=right)
for(;left<=right;left++)
{
int now=Q[left];
//left=(left+1)%MAXQ;
for(int j=tail[now];j;j=a[j].next)
{
int to=a[j].t;
if(H[now]+a[j].v<H[to])
{
H[to]=H[now]+a[j].v;
if(!vis[to])
{
vis[to]=true;
Q[++right]=to;
/*right=(right+1)%MAXQ;
Q[right]=to;*/
}
}
}
vis[now]=false;
}
}
STATE make(int real,int est,int node)
{
STATE use;
use.real=real;
use.est=est;
use.node=node;
return use;
}
priority_queue<STATE> heap;
void Astar()
{
heap.push(make(0,H[S],S));
while(!heap.empty())
{
STATE now=heap.top();
heap.pop();
num[now.node]++;
if(num[now.node]>K) continue;
if(num[T]==K)
{
ans=now.real;
return;
}
for(int i=last[now.node];i;i=a[i].next)
{
int to=a[i].t;
heap.push(make(now.real+a[i].v,H[to],to));
}
}
}
int main()
{
//freopen("input.in","r",stdin);
//freopen("output.out","w",stdout);
while(scanf("%d%d",&N,&M)!=EOF)
{
memset(num,0,sizeof(num));
memset(last,0,sizeof(last));
memset(tail,0,sizeof(tail));
tot=0;
ans=-1;
while(!heap.empty()) heap.pop();
for(int i=1;i<=M;i++)
{
int A,B,C;
scanf("%d%d%d",&A,&B,&C);
add(A,B,C);
}
scanf("%d%d%d",&S,&T,&K);
if(S==T) K++;
pre_spfa();
Astar();
printf("%d\n",ans);
}
//system("pause");
return 0;
}