POJ2449 Remmarguts' Date k短路 A*
阿新 • • 發佈:2018-11-19
題解:
短路裸題,今天看了一下,順便學習了一發
*的思想。
如果直接暴力做的話,那麼就是當
第
次出堆的時候就是答案,但是這樣的話
短路上的所有點都要出堆
次,複雜度不能承受。考慮優化,如果一個點的當前距離很短,但是它到終點的距離很長,那麼它是不優秀的,所以可以加上一個估價函式,預估他到終點的距離,每次選擇當前距離+預估距離最小的元素出堆,這樣一來每個點的出堆次數不會太多,即可通過。
值得一提的是估價函式的設定,一開始我用的是當前距離+當前點到終點最短路,我認為這樣更加接近實際答案,但是這樣MLE了,入堆節點太多,直接用當前點到終點最短路就能AC了。
程式碼:
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=1010;
const int Maxm=100010;
const int inf=2147483647;
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<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
int n,m,S,T,k;
struct Edge{int y,d,next;}e[Maxm];
int last[Maxn],len;
void ins(int x,int y,int d)
{
int t=++len;
e[t].y=y;e[t].d=d;e[t].next=last[x];last[x]=t;
}
struct Node
{
int x,t1,t2;
Node(int _x,int _t1,int _t2){x=_x,t1=_t1,t2=_t2;}
};
bool operator < (Node a,Node b){return a.t1+a.t2>b.t1+b.t2;}
int cnt[Maxn],f[Maxn];
void dijkstra()
{
memset(f,63,sizeof(f));f[T]=0;
memset(cnt,0,sizeof(cnt));
priority_queue<Node>q;q.push(Node(T,0,0));
while(!q.empty())
{
Node tmp=q.top();q.pop();
int x=tmp.x;
if(cnt[x])continue;
cnt[x]++;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(f[x]+e[i].d<f[y])
{
f[y]=f[x]+e[i].d;
q.push(Node(y,f[y],0));
}
}
}
}
void kth()
{
memset(cnt,0,sizeof(cnt));
priority_queue<Node>q;q.push(Node(S,0,f[S]));
while(!q.empty())
{
Node tmp=q.top();q.pop();
int x=tmp.x;
cnt[x]++;
if(x==T&&cnt[T]==k){printf("%d",tmp.t1);return;}
if(cnt[x]>k)continue;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
q.push(Node(y,tmp.t1+e[i].d,f[y]));
}
}
puts("-1");
}
int X[Maxm],Y[Maxm],D[Maxm];
int main()
{
n=read(),m=read();
for(int i=1;i<=m;i++)
{
X[i]=read(),Y[i]=read(),D[i]=read();
ins(Y[i],X[i],D[i]);
}
S=read(),T=read(),k=read();
if(S==T)k++;
dijkstra();
memset(last,0,sizeof(last));len=0;
for(int i=1;i<=m;i++)ins(X[i],Y[i],D[i]);
kth();
}