题意:求n个点中,a到b的第k条最短路
思路:
用最短路求出估价函数的h,再在搜索过程中记录g,利用A*求出
最开始想到的便是A*和最短路,但是脑子抽了,居然一个一个去求- -,TL了后才发现可以倒着求最短路一次搞定。
但是又发现没考虑重边的问题,又换了种姿势终于AC,感觉太习惯于直接开二维数组,这不行啊- -
当from = to时,因为还没出发就已经判定k--,所以在其相等时,k+=1
问题:
1.对算法的理解不够透彻- -
2.在题目上考虑不够全面,导致不得不重写代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <functional>
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long ll;
int vis[1005];
int low[1005];
int head[1005],head1[1005];
int from,to;
int tot;
int n,m,k;
struct edge
{
int u,v;
int len;
int next; //正向
int next1; //反向
edge() {}
edge(int x,int y,int c):u(x),v(y),len(c) {}
};
edge p[100005];
struct node
{
int po;
int g,h;
node() {}
node(int x,int y,int z):po(x),g(y),h(z) {}
bool operator<(const node& a)const
{
return g+h>a.g+a.h;
}
};
void add_edge(int u,int v,int c)
{
p[tot] = edge(u,v,c);
p[tot].next = head[u];
head[u] = tot;
p[tot].next1 = head1[v];
head1[v] = tot++;
}
void work(int c) //从to开始找出所有点到to的最短路
{
priority_queue<node>que;
memset(vis,0,sizeof(vis));
for(int i = 1; i <= n; i++)
low[i] = INF;
low[c] = 0;
que.push(node(c,0,0));
while(!que.empty())
{
node cur = que.top();
que.pop();
if(vis[cur.po])
continue;
vis[cur.po] = 1;
for(int i = head1[cur.po]; ~i; i = p[i].next1) //反向查找
{
if(low[p[i].u] > low[cur.po]+p[i].len)
{
low[p[i].u] = low[cur.po] + p[i].len;
que.push(node(p[i].u,0,low[p[i].u]));
}
}
}
}
int bfs(int t)
{
int num = 0;
priority_queue<node>que;
node cur;
cur.po = t;
cur.g = 0;
que.push(cur);
while(!que.empty())
{
cur = que.top();
que.pop();
int tp = cur.po;
if(tp == to)
{
num ++;
if(num == k)
{
return cur.g;
}
}
for(int i = head[cur.po]; ~i; i = p[i].next)
{
node tmp;
int x = p[i].v;
tmp.po = x;
tmp.g = cur.g + p[i].len;
tmp.h = low[x];
que.push(tmp);
}
}
return -1;
}
void ini()
{
tot = 0;
memset(head,-1,sizeof(head));
memset(head1,-1,sizeof(head1));
}
int main()
{
int a,b,len;
while(scanf("%d%d",&n,&m) != EOF)
{
ini();
for(int i = 0; i < m; i++)
{
scanf("%d%d%d",&a,&b,&len);
add_edge(a,b,len);
}
scanf("%d%d%d",&from,&to,&k);
work(to);
if(low[from] == INF) //如果from不能到达to
{
printf("-1\n");
continue;
}
if(from == to)
{
k++;
}
printf("%d\n",bfs(from));
}
return 0;
}