GF打dota【A_Strar第K短路A*】

本文介绍了一个基于Dota游戏背景的算法问题,涉及到寻找从起点到终点的最短路径和次短路径。通过使用SPFA算法预处理反向图的最短路径,再结合A*算法求解次短路径,提供了一种解决此类问题的有效方法。

题目链接


众所周知,GF同学喜欢打dota,而且打得非常好。今天GF和Spartan同学进行了一场大战。

现在GF拿到一张地图,地图上一共有n个地点,GF的英雄处于1号点,Spartan的基地位于n号点,

GF要尽快地选择较短的路线让他的英雄去虐掉Spartan的基地。但是Spartan早就料到了这一点,

他有可能会开挂(BS~)使用一种特别的魔法,一旦GF所走的路线的总长度等于最短路的总长度时,

GF的英雄就要和这种魔法纠缠不休。这时GF就不得不选择非最短的路线。现在请你替GF进行规划。



对于描述的解释与提醒:
1.无向路径,花费时间当然为非负值。

2.对于本题中非最短路线的定义:不管采取任何迂回、改道方式,

只要GF所走的路线总长度不等于1到n最短路的总长度时,就算做一条非最短的路线。

3.保证1~n有路可走。

 

输入:

第一行为n,m(表示一共有m条路径)
接下来m行,每行3个整数a,b,c,表示编号为a,b的点之间连着一条花费时间为c的无向路径。
接下来一行有一个整数p,p=0表示Spartan没有开挂使用这种魔法,p=1则表示使用了。

 

输出:

所花费的最短时间t,数据保证一定可以到达n。

 

 

样例输入1:
5 5
1 2 1
1 3 2
3 5 2
2 4 3
4 5 1
0


样例输入2:
5 5
1 2 1
1 3 2
3 5 2
2 4 3
4 5 1
1

 

样例输出1:
4
样例输出2:
5

 

 

对于50%的数据,1<=n,m<=5000
对于70%的数据,1<=n<=10000, 1<=m<=50000,p=0,
对于100%的数据,1<=n<=10000, 1<=m<=50000,p=1
无向图,花费时间c>=0


  就是直接求一个与最短路不同的次短路,直接就是A*问题了,求一遍反向的最短路,然后A*直接就可以了。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(x, y) make_pair(x, y)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e4 + 7, maxE = 1e5 + 7;
int N, M, head[maxN], cnt, op;
ll h[maxN];
struct Eddge
{
    int nex, to, val;
    Eddge(int a=-1, int b=0, int c=0):nex(a), to(b), val(c) {}
}edge[maxE];
inline void addEddge(int u, int v, int w)
{
    edge[cnt] = Eddge(head[u], v, w);
    head[u] = cnt++;
}
inline void _add(int u, int v, int w) { addEddge(u, v, w); addEddge(v, u, w); }
queue<int> Q;
bool inque[maxN];
inline void spfa(int st, int ed)
{
    for(int i=1; i<=N; i++)
    {
        h[i] = INF;
        inque[i] = false;
    }
    while(!Q.empty()) Q.pop();
    Q.push(st); h[st] = 0;
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop(); inque[u] = false;
        for(int i=head[u], v, w; ~i; i=edge[i].nex)
        {
            v = edge[i].to; w = edge[i].val;
            if(h[v] > h[u] + w)
            {
                h[v] = h[u] + w;
                if(!inque[v])
                {
                    inque[v] = true;
                    Q.push(v);
                }
            }
        }
    }
}
struct node
{
    int id;
    ll f, g;
    node(int a=0, ll b=0, ll c=0):id(a), f(b), g(c) {}
    friend bool operator < (node e1, node e2) { return e1.f == e2.f ? e1.g > e2.g : e1.f > e2.f; }
};
priority_queue<node> P;
inline ll A_star()
{
    if(h[N] == INF) return -1;
    while(!P.empty()) P.pop();
    P.push(node(1, h[1], 0));
    ll Min_dis = h[1];
    while(!P.empty())
    {
        node now = P.top(); P.pop();
        if(now.id == N && now.f > Min_dis) return now.f;
        for(int i=head[now.id], v; ~i; i=edge[i].nex)
        {
            v = edge[i].to;  ll w = edge[i].val;
            P.push(node(v, now.g + w + h[v], now.g + w));
        }
    }
    return -1;
}
inline void init()
{
    cnt = 0;
    for(int i=1; i<=N; i++) head[i] = -1;
}
int main()
{
    freopen("dota.in", "r", stdin);
    freopen("dota.out", "w", stdout);
    scanf("%d%d", &N, &M);
    init();
    for(int i=1, u, v, w; i<=M; i++)
    {
        scanf("%d%d%d", &u, &v, &w);
        _add(u, v, w);
    }
    scanf("%d", &op);   //要用魔法打败魔法
    spfa(N, 1);
    if(!op) printf("%lld\n", h[1]);
    else printf("%lld\n", A_star());
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值