1. 程式人生 > >POJ2449 Remmarguts' Date k短路 A*

POJ2449 Remmarguts' Date k短路 A*

題解:

k k 短路裸題,今天看了一下,順便學習了一發 A A *的思想。
如果直接暴力做的話,那麼就是當 T

T k k 次出堆的時候就是答案,但是這樣的話 k k 短路上的所有點都要出堆 k
k
次,複雜度不能承受。考慮優化,如果一個點的當前距離很短,但是它到終點的距離很長,那麼它是不優秀的,所以可以加上一個估價函式,預估他到終點的距離,每次選擇當前距離+預估距離最小的元素出堆,這樣一來每個點的出堆次數不會太多,即可通過。
值得一提的是估價函式的設定,一開始我用的是當前距離+當前點到終點最短路,我認為這樣更加接近實際答案,但是這樣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(); }