#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int oo = 1000000000, nil = 0;
int N, M, S, T, K, times[1005];
int u[200010], v[200010], w[200010], nxt[200010], pnt[1005], e;
int d[1005];
bool vis[1005], other[1005];
class node
{
public:
int n, dis;
node(int n = 0, int dis = 0) :n(n), dis(dis) {}
protected:
virtual bool operator < (const node& b) const
{
return dis > b.dis;
}
};
struct astar : public node
{
astar(int xn = 0, int xdis = 0)
{
n = xn; dis = xdis;
}
bool operator < (const astar& b) const
{
return dis + d[n] > b.dis + d[b.n];
}
};
void addedge(int a, int b, int c, bool d)
{
u[++e] = a; v[e] = b; w[e] = c;
nxt[e] = pnt[a]; pnt[a] = e; other[e] = d;
}
void init()
{
int a, b, c;
scanf("%d%d", &N, &M);
for(int i = 1; i <= M; ++i)
{
scanf("%d%d%d", &a, &b, &c);
addedge(a, b, c, false);
addedge(b, a, c, true);
}
scanf("%d%d%d", &S, &T, &K);
if(S == T)
{
++K;
}
}
void getSSSP(int s)
{
memset(d, 0x3f, sizeof(d));
memset(vis, 0, sizeof(vis));
priority_queue <node> Q;
d[s] = 0;
Q.push(node(s, 0));
while(!Q.empty())
{
node t = Q.top();
Q.pop();
vis[t.n] = true;
for(int j = pnt[t.n]; j != nil; j = nxt[j])
{
if((!vis[v[j]]) && (d[v[j]] > t.dis + w[j]) && (other[j]))
{
d[v[j]] = t.dis + w[j];
Q.push(node(v[j], d[v[j]]));
}
}
}
}
void work()
{
getSSSP(T);
memset(times, 0, sizeof(times));
priority_queue <astar> Q;
Q.push(astar(S, 0));
while(!Q.empty())
{
astar t = Q.top();
Q.pop();
++times[t.n];
if((t.n == T) && (times[t.n] == K))
{
printf("%d\n", t.dis);
return;
}
for(int j = pnt[t.n]; j != nil; j = nxt[j])
{
if(!other[j])
{
Q.push(astar(v[j], t.dis + w[j]));
}
}
}
puts("-1");
}
int main()
{
init();
work();
return 0;
}
然后因为node里的小于号被protected了,stl的priority_queue无法调用之而编译失败。如果去掉protected,node里的小于号覆盖不掉,又会使astar中的小于号没用导致WA。TUT……
题目大意
求一张有向图从S到T的第K短路(边权均为正)。
题解
首先在反向图中最短路出每个点到终点的距离,然后利用A*的思想,从起点开始可重复地搜索,估价函数为{当前走过的距离+该点到终点的最短路长度}。当终点T被第K次从堆(优先队列)中取出时,输出答案。
注意细节
S == T时要把K加上1;
某结点出队次数超过K时,可以不再考虑。
Code
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int oo = 1000000000, nil = 0;
int N, M, S, T, K, times[1005];
int u[200010], v[200010], w[200010], nxt[200010], pnt[1005], e;
int d[1005];
bool vis[1005], other[200010];
struct node
{
int n, dis;
node(int n = 0, int dis = 0) :n(n), dis(dis) {}
bool operator < (const node& b) const
{
return dis > b.dis;
}
};
struct astar
{
int n, dis;
astar(int n = 0, int dis = 0) :n(n), dis(dis) {}
bool operator < (const astar& b) const
{
return dis + d[n] > b.dis + d[b.n];
}
};
void addedge(int a, int b, int c, bool d)
{
u[++e] = a; v[e] = b; w[e] = c;
nxt[e] = pnt[a]; pnt[a] = e; other[e] = d;
}
void init()
{
int a, b, c;
scanf("%d%d", &N, &M);
for(int i = 1; i <= M; ++i)
{
scanf("%d%d%d", &a, &b, &c);
addedge(a, b, c, false);
addedge(b, a, c, true);
}
scanf("%d%d%d", &S, &T, &K);
if(S == T)
{
++K;
}
}
void getSSSP()
{
memset(d, 0x3f, sizeof(d));
memset(vis, 0, sizeof(vis));
priority_queue <node> Q;
d[T] = 0;
Q.push(node(T, 0));
while(!Q.empty())
{
node t = Q.top();
Q.pop();
vis[t.n] = true;
for(int j = pnt[t.n]; j != nil; j = nxt[j])
{
if((!vis[v[j]]) && (d[v[j]] > t.dis + w[j]) && (other[j]))
{
d[v[j]] = t.dis + w[j];
Q.push(node(v[j], d[v[j]]));
}
}
}
}
void work()
{
getSSSP();
memset(times, 0, sizeof(times));
priority_queue <astar> Q;
Q.push(astar(S, 0));
while(!Q.empty())
{
astar t = Q.top();
Q.pop();
++times[t.n];
if((t.n == T) && (times[t.n] == K))
{
printf("%d\n", t.dis);
return;
}
if(times[t.n] > K)
{
continue;
}
for(int j = pnt[t.n]; j != nil; j = nxt[j])
{
if(!other[j])
{
Q.push(astar(v[j], t.dis + w[j]));
}
}
}
puts("-1");
}
int main()
{
init();
work();
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/t14t41t/article/details/46929691