第K短路(A*算法 启发式搜索算法)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/winter2121/article/details/82533519

【启发式算法】

定义函数 h[x] = g[x] +f[x]; 其中 g[x] 是x结点的真实值,f[x]是x结点的估计剩余代价值,h[x]就是当前方案的总估计值。

在BFS过程中,以最优价值优先遍历,可以减小时间复杂度,并简化问题。A*算法的优势就是,对当前结点做一个价值估计,取出堆中最优的结点进行下一次遍历。

在求第K短路时,最无脑的思路就是,以起点s展开BFS,进行搜索,所有到达终点e的路径中,第k小的即为第k短路。借助A*算法的思想,处于结点u时,设已走过的路程为g[u],剩下的最快到达终点的路长为f[u],把g[u]+f[u]看做估价值,其实就是,已经处于当前点u,总路长再短也就g[u]+f[u]了,所以按这个值优先bfs遍历,在终点e处就能依次得到递增的路长。

【例题--2018icpc沈阳网络赛D Made In Heaven】

One day in the jail, F·F invites Jolyne Kujo (JOJO in brief) to play tennis with her. However, Pucci the father somehow knows it and wants to stop her. There are NN spots in the jail and MM roads connecting some of the spots. JOJO finds that Pucci knows the route of the former (K-1)(K−1)-th shortest path. If Pucci spots JOJO in one of these K-1K−1 routes, Pucci will use his stand Whitesnake and put the disk into JOJO's body, which means JOJO won't be able to make it to the destination. So, JOJO needs to take the KK-th quickest path to get to the destination. What's more, JOJO only has TT units of time, so she needs to hurry.

JOJO starts from spot SS, and the destination is numbered EE. It is possible that JOJO's path contains any spot more than one time. Please tell JOJO whether she can make arrive at the destination using no more than TT units of time.

Input

There are at most 5050 test cases.

The first line contains two integers NN and MM (1 \leq N \leq 1000, 0 \leq M \leq 10000)(1≤N≤1000,0≤M≤10000). Stations are numbered from 11 to NN.

The second line contains four numbers S, E, KS,E,Kand TT ( 1 \leq S,E \leq N1≤S,E≤N, S \neq ES≠E, 1 \leq K \leq 100001≤K≤10000, 1 \leq T \leq 1000000001≤T≤100000000 ).

Then MM lines follows, each line containing three numbers U, VU,V and WW (1 \leq U,V \leq N, 1 \leq W \leq 1000)(1≤U,V≤N,1≤W≤1000) . It shows that there is a directed road from UU-th spot to VV-th spot with time WW.

It is guaranteed that for any two spots there will be only one directed road from spot AA to spot BB (1 \leq A,B \leq N, A \neq B)(1≤A,B≤N,A≠B), but it is possible that both directed road <A,B><A,B> and directed road <B,A><B,A> exist.

All the test cases are generated randomly.

Output

One line containing a sentence. If it is possible for JOJO to arrive at the destination in time, output "yareyaredawa" (without quote), else output "Whitesnake!" (without quote).

样例输入复制

2 2
1 2 2 14
1 2 5
2 1 4

样例输出复制

yareyaredawa

题目来源

ACM-ICPC 2018 沈阳赛区网络预赛

【题意】

有向图,n点m边,求s->e是否存在k中方案的路径,使得路程<=T

【分析】

第k短路小于等于T即可。

从终点到起点求一遍单源最短路,作为估计剩余值。

从起点向终点BFS,A*思想,已走路+剩余最短路作为估计值。

【代码】

/****
***author: winter2121
****/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX=4e4+5;
const int INF=0x3f3f3f3f;

struct graph{
    struct node{
        int t,next,len;
    }edge[MAX];
    int head[MAX],cnt;
    void init(int n)
    {
        memset(head,-1,sizeof(head[0])*(n+1));cnt=0;
    }
    void addedge(int u,int v,int len)
    {
        edge[cnt]=node{v,head[u],len};
        head[u]=cnt++;
    }
}G,R;

int n,m,s,e,k,T;
ll dis[MAX];
bool inq[MAX];
void diji(graph &G,int s,int e)
{
    for(int i=0;i<=n;i++)dis[i]=INF,inq[i]=0;
    dis[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front(); q.pop();
        inq[u]=0;
        for(int i=G.head[u];~i;i=G.edge[i].next)
        {
            int v=G.edge[i].t;
            if(dis[v]>dis[u]+G.edge[i].len)
            {
                dis[v]=dis[u]+G.edge[i].len;
                if(!inq[v])
                    inq[v]=1,q.push(v);
            }
        }
    }
}

struct Anode{   //优先h=real+need,f相等时按实际值real小的
    ll real,need;//实际值,预算
    int id;
    friend bool operator<(Anode a,Anode b)
    {
       // if(a.f+a.g==b.f+b.g)return a.g>b.g;
        return a.need+a.real>b.need+b.real;
    }
};
ll Astar(graph &G,int s,int e,int k)
{
    if(s==e)k++; //最短路必为0,而题目中最短路必须是正数,故排除0
    if(dis[s]==INF)return -1; //se没有通路,会导致在s的连通块里一直转圈
    int cnt=0;
    priority_queue<Anode> q;
    q.push(Anode{0,dis[s],s});
    while(!q.empty())
    {
        Anode u=q.top(); q.pop();
        if(u.id==e)
        {
            cnt++;
            if(k==cnt)return u.real;
        }
        for(int i=G.head[u.id];~i;i=G.edge[i].next)
        {
            int v=G.edge[i].t;
            q.push(Anode{u.real+G.edge[i].len,dis[v],v});
        }
    }
    return -1;
}
int main()
{
    while(~scanf("%d%d%d%d%d%d",&n,&m,&s,&e,&k,&T))
    {
        G.init(n);
        R.init(n);
        int a,b,c;
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d%d",&a,&b,&c);
            G.addedge(a,b,c);
            R.addedge(b,a,c);
        }
        diji(R,e,s);
        int A=Astar(G,s,e,k);
        if(A>=0&&A<=T)printf("yareyaredawa\n");
        else printf("Whitesnake!\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/winter2121/article/details/82533519