http://poj.org/problem?id=2449
第k短路 刚开始上网找了分标准解法 没看懂呀 汗 然后看别人都用了A*算法 我也不知道是
什么东西
如果我们用队列枚举的话 当第k次出现终点 则这时就是到终点的第k短路
但是这样队列是承受不住的 因为数据会太多
对于这道题 思路好像基本上就是
构造一个函数 f(i)=g(i)+h(i) g为出发点到i的最短距离 h为终点到i的最短距离
f 为他们的和但每次取f最小的点进行更新
直到终点出现第k次 既为答案
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<queue> #include<string.h> using namespace std; const int N=1001; const int M=1000005; const int MAX=0x5fffffff; struct ss { int x,y; int d; }mem[M]; int head[N]; struct to { int j,k; int next; }side[M]; struct node { int f,g; int x; bool operator <(const node a) const { if(a.f==f) return a.g<g; return a.f<f; } }; priority_queue< node >str; void build(int x,int i) { side[i].next=head[x]; head[x]=i; } int dist[N]; int had[N]; void spfa(int s,int n) { queue<int>st; memset(had,0,sizeof(had)); for(int i=1;i<=n;++i) dist[i]=MAX; dist[s]=0; had[s]=1; st.push(s); while(!st.empty())//求到终点最短距离 { int x=st.front(); st.pop(); had[x]=0; int t=head[x]; while(t!=-1) { if(dist[side[t].j]>dist[x]+side[t].k) { dist[side[t].j]=dist[x]+side[t].k; if(!had[side[t].j]) { st.push(side[t].j); had[side[t].j]=1; } } t=side[t].next; } } } int Astar(int S,int T,int k,int n) { if(dist[S]==MAX) return -1; if(S==T)//这里坑嗲 ++k; while(!str.empty()) str.pop(); node k1,k2; k1.f=dist[S]; k1.x=S; k1.g=0; str.push(k1);//用优先队列实现 memset(had,0,sizeof(had)); while(!str.empty()) { k1=str.top();//每次取f最小 str.pop(); ++had[k1.x]; if(had[T]==k)//不断寻找 直到终点第 k 次出现 就是第k短路 return k1.g; if(had[k1.x]>k) continue; int t=head[k1.x]; while(t!=-1) { k2.x=side[t].j; if(dist[k2.x]==MAX) { t=side[t].next;continue; } k2.g=k1.g+side[t].k; k2.f=k2.g+dist[k2.x]; str.push(k2); t=side[t].next; } } return -1; } int main() { freopen("data.txt","r",stdin); int n,m,k,S,T; while(scanf("%d %d",&n,&m)!=EOF) { memset(head,-1,sizeof(head)); for(int i=0;i<m;++i) { scanf("%d %d %d",&mem[i].x,&mem[i].y,&mem[i].d); side[i].j=mem[i].x; side[i].k=mem[i].d;//建反向图 build(mem[i].y,i); } scanf("%d %d %d",&S,&T,&k); spfa(T,n);//求到终点 最短路 memset(head,-1,sizeof(head)); for(int i=0;i<m;++i) { side[i].j=mem[i].y; build(mem[i].x,i);//建正向边 } printf("%d\n",Astar(S,T,k,n));//A× } return 0; }