Time Limit: 4000MS | Memory Limit: 65536K | |
Total Submissions: 30980 | Accepted: 8462 |
Description
Input
Output
Sample Input
2 2 1 2 5 2 1 4 1 2 2
Sample Output
14
题意:
n个点m条边的有向图,给定起点终点和k,求出从起点到终点的第k短路
设起点为S,终点为T,步骤:
①求出反向图中T到所有点的最短路,bet[x]表示从T到x的最短路
②定义结构体s,里面包含x(当前点);d(从S到x总共走的路程);
f(估价函数,f = d+bet[x])
③创建结构体s的优先队列,其中队列顶端f最小(按f从大到小排)
④SPFA,如果当前是第p次到达终点,那么结构体里的d就是第p短路的长度!
复杂度:O(nk)
#include
#include
#include
using namespace std;
#define inf 1044266558
int n, m, k, s, t;
int head[2010], bet[2010], vis[2010], head2[2010], cnt, cnt2;
typedef struct Edge
{
int to, c;
int next;
}Edge;
Edge G2[300050], G[300050];
void Add(int a, int b, int c)
{
cnt++;
G[cnt].next = head[a];
head[a] = cnt;
G[cnt].to = b;
G[cnt].c = c;
}
void Add1(int a, int b, int c)
{
cnt2++;
G2[cnt2].next = head2[a];
head2[a] = cnt2;
G2[cnt2].to = b;
G2[cnt2].c = c;
}
queue q;
typedef struct Res
{
int f; //f是估价函数,等于d加上从x到终点T的最短路
int x, d; //x是当前到达的点,d表示从起点s到x总共走的路程
bool operator < (const Res &b) const //队列的顶端f最小
{
if(f>b.f)
return 1;
return 0;
}
}Res;
Res u, v;
priority_queue vq;
void Solve()
{
int now, i, tc;
now = 0;
u.f = bet[s], u.x = s, u.d = 0;
vq.push(u);
while(vq.empty()==0)
{
u = vq.top();
vq.pop();
if(u.x==t)
now++;
if(now==k)
{
printf("%d\n", u.d);
return;
}
for(i=head[u.x];i;i=G[i].next)
{
tc = G[i].to;
v = u;
v.x = tc, v.d += G[i].c, v.f = bet[v.x]+v.d;
vq.push(v);
}
}
printf("-1\n");
}
int main(void)
{
int i, x, y, c;
while(scanf("%d%d", &n, &m)!=EOF)
{
memset(head, 0, sizeof(head));
memset(head2, 0, sizeof(head2));
cnt = cnt2 = 0;
for(i=1;i<=m;i++)
{
scanf("%d%d%d", &x, &y, &c);
Add(x, y, c);
Add1(y, x, c);
}
scanf("%d%d%d", &s, &t, &k);
if(s==t)
k++;
memset(bet, 62, sizeof(bet));
memset(vis, 0, sizeof(vis));
bet[t] = 0, vis[t] = 1;
q.push(t);
while(q.empty()==0)
{
x = q.front();
q.pop();
vis[x] = 0;
for(i=head2[x];i;i=G2[i].next)
{
y = G2[i].to;
if(bet[y]>bet[x]+G2[i].c)
{
bet[y] = bet[x]+G2[i].c;
if(vis[y]==0)
{
q.push(y);
vis[y] = 1;
}
}
}
}
if(bet[s]==inf)
printf("-1\n");
else
{
Solve();
while(vq.empty()==0)
vq.pop();
}
}
}