POJ 2449 Remmarguts‘ Date---SPFA求评估函数 + A*最小堆BFS

2023-05-16

POJ 2449 Remmarguts’ Date

Time Limit: 4000MS Memory Limit: 65536K

Description

“Good man never makes girls wait or breaks an appointment!” said the mandarin duck father. Softly touching his little ducks’ head, he told them a story.

“Prince Remmarguts lives in his kingdom UDF – United Delta of Freedom. One day their neighboring country sent them Princess Uyuw on a diplomatic mission.”

“Erenow, the princess sent Remmarguts a letter, informing him that she would come to the hall and hold commercial talks with UDF if and only if the prince go and meet her via the K-th shortest path. (in fact, Uyuw does not want to come at all)”

Being interested in the trade development and such a lovely girl, Prince Remmarguts really became enamored. He needs you - the prime minister’s help!

DETAILS: UDF’s capital consists of N stations. The hall is numbered S, while the station numbered T denotes prince’ current place. M muddy directed sideways connect some of the stations. Remmarguts’ path to welcome the princess might include the same station twice or more than twice, even it is the station with number S or T. Different paths with same length will be considered disparate.

Input

The first line contains two integer numbers N and M (1 <= N <= 1000, 0 <= M <= 100000). Stations are numbered from 1 to N. Each of the following M lines contains three integer numbers A, B and T (1 <= A, B <= N, 1 <= T <= 100). It shows that there is a directed sideway from A-th station to B-th station with time T.

The last line consists of three integer numbers S, T and K (1 <= S, T <= N, 1 <= K <= 1000).

Output

A single line consisting of a single integer number: the length (time required) to welcome Princess Uyuw using the K-th shortest path. If K-th shortest path does not exist, you should output “-1” (without quotes) instead.

Sample Input

2 2
1 2 5
2 1 4
1 2 2

Sample Output

14

思路

  1. 先用SPFA对终点求反向最短路(这里是有向图,要把边反向存储在另一空间内),得到了终点到各个点的最短路径
  2. 若不能到达源点说明无解返回-1,若终点和源点相同,那么要把k+ 1,因为这个路径为0,无效。
  3. 然后BFS中的优先队列重写比较函数,选取评估结果 + dist 最优的点进入下一步,实现A*的思路。

Code

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;

const int maxn = 1e3 + 3;
const int maxm = 1e5 + 3;
const int inf = 0x3f3f3f3f;

int f[maxn], head[maxn], reverse_head[maxn];
bool inq[maxn];

struct way {
    int node, dist, f;
    way(int node = 0, int dist = 0, int f = 0) : node(node), dist(dist), f(f) {}

    bool operator < (const way& other) const{
        if (f == other.f) return dist > other.dist;
        return f > other.f;
    }   
};

struct edge {
    int to, val, next;
    edge(int to = 0, int val = 0, int next = 0) : to(to), val(val), next(next){}
}edges[maxm], reverse_edges[maxm];

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar();
    return x * f;
}

void spfa(int s) {
    memset(f, inf, sizeof(f));
    memset(inq, false, sizeof(inq));
    f[s] = 0; 
    queue<int> q;
    q.push(s);
    inq[s] = true;
    while (q.size()) {
        int now = q.front(); q.pop();
        inq[now] = false;
        for (int i = reverse_head[now]; i; i = reverse_edges[i].next) {
            int to = reverse_edges[i].to, val = reverse_edges[i].val;
            if (f[to] > f[now] + val) {
                f[to] = f[now] + val;
                if (!inq[to]) {
                    q.push(to);
                    inq[to] = true;
                }
            }
        }
    }
}

int bfs(int s, int e, int k) {
    // 找最终点到各个点的最短路径,确立评估函数f,依次使用A*算法来帮助小根堆BFS优化
    spfa(e);
    // 若是没有通路直接返回-1
    if (f[s] == inf) return -1;
    // 当前找到第cnt短路
    int now_k = 0;
    // 如果起点就是终点
    if (s == e) k++;

    priority_queue<way> pq;
    pq.push(way(s, 0, f[s]));
    
    while (pq.size()) {
        way top = pq.top(); pq.pop();
        int now = top.node, dist = top.dist;
        // 若找到第k短路返回
        if (now == e) {
            ++now_k;
            if (now_k == k) return dist;
        }

        for (int i = head[now]; i; i = edges[i].next) {
            int to = edges[i].to, new_dist = dist + edges[i].val;
            pq.push(way(to, new_dist, new_dist + f[to]));
        }
    }
    return -1;
}

int main() {
    int n, m, a, b, t, s, e, k;
    while (cin >> n >> m) {
        memset(edges, 0, sizeof(edges));
        memset(reverse_edges, 0, sizeof(reverse_edges));
        memset(head, 0, sizeof(head));
        memset(reverse_head, 0, sizeof(reverse_head));

        for (int i = 1; i <= m; i++) {
            a = read(); b = read(); t = read();
            edges[i] = edge(b, t, head[a]);
            head[a] = i;
            // 为了反向找终点的最短路的处理
            reverse_edges[i] = edge(a, t, reverse_head[b]);
            reverse_head[b] = i;
        }

        s = read(); e = read(); k = read();

        cout << bfs(s, e, k) << endl;
    }
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

POJ 2449 Remmarguts‘ Date---SPFA求评估函数 + A*最小堆BFS 的相关文章

  • 具有日期和名称标准的 SUMIFS...仅限月份和年份

    我正在尝试获取 SUMIFS 公式来检查日期列 并仅对与标准日期的匹配年份和月份相对应的值求和 我还希望此 SUMIFS 包含名称标准和日期 IE 单元格 A1 SUMIFS Sheet1 O O Sheet1 D D Sheet2 DAT
  • 时间序列,将月度数据改为季度

    现在我有一些每月数据 例如 1 1 90 620 2 1 90 591 3 1 90 574 4 1 90 542 5 1 90 534 6 1 90 545 etc 如果我使用 ts 函数 很容易将数据转换为时间序列结构 例如 Jan F
  • 从 dask 数据框中的日期时间序列获取年份和星期?

    如果我有一个 Pandas 数据框和一个日期时间类型的列 我可以按如下方式获取年份 df year df date dt year 对于 dask 数据框 这是行不通的 如果我先计算 像这样 df year df date compute
  • 从字符串到日期的日期格式

    我正在使用上传的 csv 进行日期格式化 其中日期是具有以下格式的字符串 10 30 2021 8 41 PM 我试图在谷歌大查询中将其更改为 mm dd yyyy 但不断收到错误消息 提示 无效日期 或 无效日期时间 我尝试过使用子字符串
  • MySQL创建表中的日期格式

    我必须使用 MySql 创建一个表 它可以按以下格式存储日期 我尝试过如下 CREATE TABLE birth date DATE 但它不起作用 因为日期格式是 YYYY MM DD 我该怎么办 谢谢 MySQL 或几乎任何其他数据库 中
  • 同一活动中的多个日期选择器

    我对 Android 平台完全陌生 在学习开发过程的同时一直在构建应用程序 目前 我正在开展一项活动 需要部署 2 个日期选择器 一个是 开始日期 另一个是 结束日期 我一直在关注 Android 开发者页面上的 DatePicker 教程
  • Breejs:日期未设置为正确的时间

    我注意到 如果从服务器返回的日期属性的值为 2013 07 11T17 11 04 700 则微风会将值更改为 Thu Jul 11 19 11 04 UTC 0200 2013 请注意 现在时间提前了 2 小时 我在保存实体时已经遇到了这
  • 覆盖乔达一周的第一天?

    是否有可能覆盖乔达弱的第一天sunday 因为 Joda 使用Monday作为一周的第一天 如果有办法的话 谁能解释一下 我在 SOF 中提到了以下主题 乔达时间 一周的第一天 https stackoverflow com questio
  • 如何按日期升序对对象进行排序?

    如果我有一个对象列表 var objectList LIST OF OBJECT each object列表中包含三个属性 name date gender 如何按 对列表中的对象进行排序date 属性升序 the date 属性包含字符串
  • 在批处理文件中添加 +1 到日期

    我有一个批处理文件 可以很好地创建今天的日期 现在我需要更新它以显示明天的日期 任何帮助深表感谢 echo off set TimeStamp 12 00 00 FOR F TOKENS 1 DELIMS A IN DATE T DO SE
  • 如何格式化 LocalTime 变量

    我对 Java windowbuilder 很陌生 这是我第一个项目的一部分 String starttime JOptionPane showInputDialog null What time would you like to sta
  • 在 PowerShell 中提取 EXIF 数据的简单方法?

    我一直在研究使用 PowerShell 提取 EXIF 数据的各种方法 但到目前为止我发现它相当复杂 一些here http blog cincura net 233463 renaming files based on exif data
  • 比较休眠映射的日期?

    如何使用 Hibernate 将日期从 java 对象映射到数据库 我尝试不同的方法 但我对它们不满意 为什么 让我解释一下我的问题 我有以下类 1 包括我调用的主要方法和以下映射 2 当您查看控制台输出时 您可以看到有关此方法的问题 fa
  • 如何在 JavaScript 中将本地化日期转换为标准日期?

    我正在编写一段 JavaScript 代码来对包含日期 包含本地化日期 和其他字段的数据表进行排序 例如 lunes 29 de agosto de 2011 field1 field2 lunes 28 de agosto de 2011
  • QuickSight - 随着时间的推移活动事件的计数[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我在 QuickSight 中有一个事件数据集 其中每条记录都有两个日期字段 开始日期和结束日期 如果 T 介于 startDate
  • 更改Java日期的格式[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我有格式为 Date 的对象 107 2013 12 00 00 AM 我的期望值 2013 07 01 我如何做到这一点 我正在尝试使用这
  • 如何将整数日期转换为格式化日期字符串(即 2012009 到 2/01/2009)

    有任何想法吗 我想不出任何办法 我有一个从 csv 文件加载的日期列表 它们被保存为所有整数 或者更确切地说是一串整数 即 2009 年 1 月 1 日 1012009 关于如何将 1012009 变成 1 01 2009 有什么想法吗 T
  • 将年月格式转换为 POSIXct [重复]

    这个问题在这里已经有答案了 我有一些年月形式的数据 我想将其格式化以用于绘图ggplot date lt c 2016 03 2016 04 2016 05 2016 06 2016 07 2016 08 2016 09 2016 10 2
  • 如何将完整的日期格式拆分为日期和时间?

    我有很多格式为我的示例所示的字符串 我必须解析它们 我正在尝试确定今天是哪根弦 我的问题是 时间快到了 我只需要比较那个日期 接下来我想检查时间是否在 after 和 before 的两个时间戳 HH mm ss 之间 但存在问题 日期几乎
  • R:如何获取该月的周数

    我是 R 新手 我想要该日期所属月份的周数 通过使用以下代码 gt CurrentDate lt Sys Date gt Week Number lt format CurrentDate format U gt Week Number 3

随机推荐