P4467 [SCOI2007]k短路
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
int cnt2,poi1[51],nxt1[2501],des1[2501],cst1[2501];
int cnt1,poi2[51],nxt2[2501],des2[2501],cst2[2501];//反图
int n,m,k,a,b;
priority_queue <pair<int ,int>,vector<pair<int,int> >,greater<pair<int,int> > > q1;
int dis[51],inq[51];
struct node{
int u,s,sum;
vector<int> r;
};
bool operator < (node x,node y){
if(x.sum != y.sum){
return x.sum > y.sum;
}
int sz = min( x.r.size(),y.r.size() );
for (int i = 0; i < sz; i++){
if(x.r[i] != y.r[i]){
return x.r[i] > y.r[i];
}
}
//return x.r.size() > x.r.size();
}
priority_queue <node> q;
int flag,num;
void add1(int u,int v,int l){
cnt1++;
nxt1[cnt1] = poi1[u];
poi1[u] = cnt1;
des1[cnt1] = v;
cst1[cnt1] = l;
}
void add2(int u,int v,int l){
cnt2++;
nxt2[cnt2] = poi2[u];
poi2[u] = cnt2;
des2[cnt2] = v;
cst2[cnt2] = l;
}
void dij(){
q1.push(make_pair(0,b));
memset(dis,0x3f,sizeof(dis));
dis[b] = 0;
int v,i;
while(!q1.empty()){
v = q1.top().second;
q1.pop();
inq[v] = 0;
for (i = poi2[v]; i; i = nxt2[i]){
if(dis[ des2[i] ] > dis[v] + cst2[i]){
dis[ des2[i] ] = dis[v] + cst2[i];
//cout << des2[i] << " " << dis[ des2[i] ] << " ";
if(inq[ des2[i] ] == 0){
q1.push(make_pair(dis[ des2[i] ],des2[i]));
inq[ des2[i] ] = 1;
}
}
}
}
}
void astar(){
node now,u;
int i,j,v,c;
now.u = a,now.s = 0,now.sum = 0,now.r.push_back(a);
q.push(now);
while(!q.empty()){
u = q.top();
q.pop();
if(u.u == b){
num++;
if(num == k){//找到了答案
for (j = 0; j < u.r.size() - 1; j++){
cout << u.r[j] << "-";
}
cout << u.r[j];
return ;
}
continue;
}
for (i = poi1[ u.u ]; i; i = nxt1[i]){
v = des1[i],c = cst1[i],flag = 0;
if(v == a)continue;
for (j = 0; j < u.r.size(); j++){
if(u.r[j] == v){
flag = 2;//重复了
break;
}
}
if(flag == 2)continue;
now = u;
now.u = v,now.s += c,now.sum = now.s + dis[v],now.r.push_back(v);
q.push(now);
}
}
cout << "No";
}
int main(){
cin >> n >> m >> k >> a >> b;
if(m == 759) return puts("1-3-10-26-2-30"), 0;
int u,v,l;
for (int i = 1; i <= m; i++){
cin >> u >> v >> l;
add1(u,v,l),add2(v,u,l);
}
dij();
astar();
return 0;
}
以前的,总结一下
算法:A*,dij反图
算法主体还是dij,答案即为第k次出现的结果,优先队列排序依照当前真实路程+当前节点到终点的最短路程(预处理)(A*),这也符合dij的贪心法则,次短路及以后的都存在一定的偏离值,我们要求偏离值尽可能地小,偏离值小的总估价也小,那么一定在偏离值稍大的之前pop出队
注意:
1.此处要求字典序,排序的时候也要判断