ICPC2018南昌网络赛——Made In Heaven(天堂制造)(Kth 短路)

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 N spots in the jail and  M roads connecting some of the spots. JOJO finds that Pucci knows the route of the former  (K-1)-th shortest path. If Pucci spots JOJO in one of these K-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  K-th quickest path to get to the destination. What’s more, JOJO only has T units of time, so she needs to hurry.
JOJO starts from spot S, and the destination is numbered E. 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 T units of time.

有一天,在监狱里,FF邀请JOJO(不是JO厨不知道人名..)和她一块打网球。但是Pucci不知道怎么着的就知道了这件事并且想阻止她。在监狱里有N个地点和M条路连接这些地点。JOJO发现Pucci知道第K-1短路,如果Pucci发现JOJO在K-1短路里的一条的话,Pucci就会用他的站立白蛇并且在JOJO身体里放入磁盘,这意味着JOJO没法到达目的地。所以JOJO需要去走第K短路到达目的地。而且,JOJO只有T单位的时间,所以她得快点。JOJO从S出发,目的地是E。JOJO的路线可能不止一次走过某一个点。请告诉JOJO是否他可以在不超过T单位时间内到达目的地。

输入

There are at most 50 test cases.

至多50组数据
The first line contains two integers N and M (1≤N≤1000,0≤M≤10000). Stations are numbered from 1 to N.

第一行包含两个整数N和M。站点由1至N标号。
The second line contains four numbers S, E, Kand T( 1≤S,E≤N,S≠E,1≤K≤10000, 1≤T≤100000000).

第二行包含是个数字:S E K T
Then M lines follows, each line containing three numbers U, V and W (1≤U,V≤N,1≤W≤1000) . It shows that there is a directed road from U-th spot to V-th spot with time W.

接下来是M行,每一行包含三个数字U,V,W。这代表在第U个点和第V个点之间存在一条花费时间W的路


It is guaranteed that for any two spots there will be only one directed road from spot A to spot B(1≤A,B≤N,A≠B), but it is possible that both directed road <A,B> and directed road <B,A> exist.
All the test cases are generated randomly.

保证两点之间有且仅有一条从A到B的有向边,但是可能A,B和B,A之间都存在有向边。

所有测试数据均为随机生成

输出

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).

输出一行,包含一个句子。如果JOJO可以到达,那么输出“yareyaredawa”,否则输出“Whitesnake!”。

输入

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

输出

yareyaredawa

由题意即可知这是一道第K短路的模板题。

K短路与最短路算法之间有不同的几点:

  1. 引进了新的Astar算法。Astar算法就是基于最佳优先搜索并利用实际值+预期值这样的一个指标对当下可选的路线进行评估(评估排序用优先队列实现),从而最终得出特定的结果。
  2. 双向建图(有向图),第一遍最短路算法反向搜索,第二遍Astar算法正向搜索

其中反向搜索是为了确定各点与终点的最短路关系(考虑到Astar算法里的预期值),正向搜索是为了从起点开始评估各点的价值并作出判断。 

综上,有如下思路:

  1. 在一切工作开始之前,进行必要的初始化
  2. 链式前向星正向建图,供Astar算法使用。反向建图,供最短路算法使用。
  3. 运用最短路算法找到所有点与终点间的最短距离
  4. 运用Astar找到第K替换短路(找不到另说)
#include <iostream>
#include <cstdio>
//#include <bits/stdc++.h>
#include <queue>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf("%lld",&a)
#define din(a) scanf("%d",&a)
#define printlnlld(a) printf("%lld\n",a)
#define printlnd(a) printf("%d\n",a)
#define printlld(a) printf("%lld",a)
#define printd(a) printf("%d",a)
#define reset(a,b) memset(a,b,sizeof(a))
const long long int INF=0x3f3f3f3f;
using namespace std;
const double PI=acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod=1000000007;
const int tool_const=1999112620000907;
const int tool_const2=33;
inline ll lldcin()
{
    ll tmp=0,si=1;
    char c=getchar();
    while(c>'9'||c<'0')
    {
        if(c=='-')
            si=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        tmp=tmp*10+c-'0';
        c=getchar();
    }
    return si*tmp;
}
///Schlacht von Stalingrad
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
struct node
{
    int to,next,weight;
}nodesa[111000],nodesb[111000];
struct buck
{
    int reality,expection;//真实走过的路程和当前点预期要走过的路程
    int id;//当前点id
};
int headsa[111000],headsb[111000];
int dist[1100],frequency[1100];
bool vis[1100];
int cnt=1;
void cons(int from,int to,int burden)
{
   nodesa[cnt]=node{to,headsa[from],burden};//正向建图
   headsa[from]=cnt;
   nodesb[cnt]=node{from,headsb[to],burden};//反向建图
   headsb[to]=cnt++;
}
void recover()
{
    reset(headsa,-1);
    reset(headsb,-1);
    cnt=1;
    reset(vis,0);
    reset(dist,0x3f);
    reset(frequency,0);
}
void SPFA(int st)//最短路算法-spfa
{
    dist[st]=0;
    queue<int>q;
    q.push(st);
    vis[st]=true;
    while(!q.empty())
    {
        int current=q.front();
        q.pop();
        vis[current]=false;
        //cout<<headsb[current]<<endl;
        for(int i=headsb[current];i!=-1;i=nodesb[i].next)
        {
            int tmp=nodesb[i].to;
            if(dist[tmp]>dist[current]+nodesb[i].weight)
            {
                dist[tmp]=dist[current]+nodesb[i].weight;
                if(vis[tmp]==false)
                {
                    vis[tmp]=true;
                    q.push(tmp);
                }
            }
        }
    }
}
bool operator<(buck a,buck b)//用于优先队列的运算符重载。
{
    return a.expection+a.reality>b.reality+b.expection;
}
int ASTAR(int from,int to,int kth)
{
    int totality=0;
    if(from==to)//如果起始点相同(环路),那么把Kth加一用来滤掉0的情况(0肯定是最短路),但是如果题目中说明0是允许的话就不要修改kth了。
        kth++;
    if(dist[from]==INF)//终点压根就和起点不连通
        return -1;
    priority_queue<buck>pq;
    pq.push(buck{0,dist[from],from});
    while(!pq.empty())
    {
        buck current=pq.top();
        pq.pop();
        //cout<<current.reality<<endl;
        if(current.id==to)//第totality次到达终点
        {
            totality++;
            if(kth==totality)
                return current.reality+current.expection;
        }
        for(int i=headsa[current.id];i!=-1;i=nodesa[i].next)
        {
            int tmp=nodesa[i].to;
            pq.push(buck{current.reality+nodesa[i].weight,dist[tmp],tmp});
        }
    }
    return -1;
}
int DETERMINATION()
{
   ll point,edge;
   while(cin>>point>>edge)
   {
      recover();
      int tmp1,tmp2,tmp3;
      int st,ed,kth,tim;
      cin>>st>>ed>>kth>>tim;
      for(int i=1;i<=edge;i++)
      {
          cin>>tmp1>>tmp2>>tmp3;
          cons(tmp1,tmp2,tmp3);
      }
      //cout<<dist[st]<<endl;
      SPFA(ed);
      int ans=ASTAR(st,ed,kth);
      //cout<<ans<<endl;
      if(ans>tim||ans==-1)
         cout<<"Whitesnake!"<<endl;
      else
         cout<<"yareyaredawa"<<endl;
   }
   return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43874261/article/details/89840482