• Roadblocks题解


    USACO的快乐农场题目

    题目大意
    求结点1到n的严格次次短路径。

    因为不久前刚刚看过了最短路计数这道题目,所以就想在求最短路的时候,用dis数组记录最短路和次短路,然后就愉快的打完了代码,过了样例,然后50……

    下面是50分代码

    #include <bits/stdc++.h>
    #define id tmp.second
    #define di tmp.first
    using namespace std;
    typedef pair<int, int> PI;
    const int M = 300500;
    int n, r, head[M], tot, dis[M][2], vis[M];
    struct EDGE{
    int v, w, nxt;
    }e[M];
    priority_queue<PI, vector<PI>, greater<PI> > q;
    PI tmp;
    
    void add(int x, int y, int z)
    {
    e[++tot].v = y, e[tot].nxt = head[x], e[tot].w = z, head[x] = tot;
    }
    
    void Dijkstra()
    {
    memset(dis, 0x4f, sizeof(dis));
    dis[1][0] = dis[1][1] = 0;
    q.push(make_pair(0, 1));
    while (!q.empty())
    {
    tmp = q.top(), q.pop();
    if (vis[id]) continue;
    vis[id] = 1;
    for (int i = head[id]; i; i = e[i].nxt)
    {
    if (dis[e[i].v][0] > di + e[i].w)
    {
    dis[e[i].v][1] = dis[e[i].v][0], dis[e[i].v][0] = di + e[i].w;
    if (!vis[e[i].v]) q.push(make_pair(dis[e[i].v][0], e[i].v));
    }
    else if (dis[e[i].v][1] > di + e[i].w) dis[e[i].v][1] = di + e[i].w;
    }
    }
    }
    
    int main()
    {
    int x, y, z;
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> r;
    for (int i = 1; i <= r; ++i) cin >> x >> y >> z, add(x, y, z), add(y, x, z);
    Dijkstra();
    printf("%d", dis[n][1]);
    return 0;
    }
    

    然后,我重新想了想我在求最短路的时候的判断,发现50这个样子写,最小值可能会覆盖次小值,因为我只判断了一遍的范围,没有限制次小值严格小于最小值。而且题目要求一条路可以重复走多次,所以我增加了每个点可以经过的次数。
    判断部分就成了这个样子

    for (int i = head[id]; i; i = e[i].nxt)
    {
    if (dis[e[i].v][0] > di + e[i].w)
    {
    dis[e[i].v][1] = dis[e[i].v][0], dis[e[i].v][0] = di + e[i].w;
    if (dis[e[i].v][1] > dis[id][1] + e[i].w && dis[e[i].v][0] < dis[id][1] + e[i].w)
    dis[e[i].v][1] = dis[id][1] + e[i].w;
    if (vis[e[i].v] < 2) q.push(make_pair(dis[e[i].v][0], e[i].v));
    }
    else
    if (dis[e[i].v][1] > di + e[i].w && dis[e[i].v][0] < di + e[i].w)
    {
    dis[e[i].v][1] = di + e[i].w;
    q.push(make_pair(dis[e[i].v][0], e[i].v));
    }
    else
    if (dis[e[i].v][1] > dis[id][1] + e[i].w && dis[e[i].v][0] < dis[id][1] + e[i].w)
    dis[e[i].v][1] = dis[id][1] + e[i].w;
    }
    

    这样就过了90分!
    然后下载了错误数据,发现还是错在了一条边可以走多次的问题上。因为走多次的话,第一个点的次短路就不一定是0了,所以我把初始化只改成了初始化1号点的最短路。这样就过了这个题。
    下面是AC代码

    #include <bits/stdc++.h>
    #define id tmp.second
    #define di tmp.first
    using namespace std;
    typedef pair<int, int> PI;
    const int M = 300500;
    int n, r, head[M], tot, dis[M][2], vis[M];
    struct EDGE{
    int v, w, nxt;
    }e[M];
    priority_queue<PI, vector<PI>, greater<PI> > q;
    PI tmp;
    
    void add(int x, int y, int z)
    {
    e[++tot].v = y, e[tot].nxt = head[x], e[tot].w = z, head[x] = tot;
    }
    
    void Dijkstra()
    {
    memset(dis, 0x4f, sizeof(dis));
    dis[1][0] = 0;
    q.push(make_pair(0, 1));
    while (!q.empty())
    {
    tmp = q.top(), q.pop();
    if (vis[id] == 2) continue;
    ++vis[id];
    for (int i = head[id]; i; i = e[i].nxt)
    {
    if (dis[e[i].v][0] > di + e[i].w)
    {
    dis[e[i].v][1] = dis[e[i].v][0], dis[e[i].v][0] = di + e[i].w;
    if (dis[e[i].v][1] > dis[id][1] + e[i].w && dis[e[i].v][0] < dis[id][1] + e[i].w)
    dis[e[i].v][1] = dis[id][1] + e[i].w;
    if (vis[e[i].v] < 2) q.push(make_pair(dis[e[i].v][0], e[i].v));
    }
    else
    if (dis[e[i].v][1] > di + e[i].w && dis[e[i].v][0] < di + e[i].w)
    {
    dis[e[i].v][1] = di + e[i].w;
    if (vis[e[i].v] < 2) q.push(make_pair(dis[e[i].v][0], e[i].v));
    }
    else
    if (dis[e[i].v][1] > dis[id][1] + e[i].w && dis[e[i].v][0] < dis[id][1] + e[i].w)
    dis[e[i].v][1] = dis[id][1] + e[i].w;
    }
    }
    }
    
    int main()
    {
    int x, y, z;
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> r;
    for (int i = 1; i <= r; ++i) cin >> x >> y >> z, add(x, y, z), add(y, x, z);
    Dijkstra();
    printf("%d", dis[n][1]);
    return 0;
    }
    

  • 相关阅读:
    数据库 | 建表常用语句
    心得 | 撰写项目申报书
    工具 | 时间转化
    SpringBoot | 启动异常 | 显示bulid success 无 error信息
    120. 三角形最小路径和
    63. 不同路径 II
    SpringBoot | Velocity template
    SpringBoot | quartz | @DisallowConcurrentExecution
    SpringBoot | Hibernate @Transient 注解
    Java | 基础归纳 | 静态方法与实例方法的区别
  • 原文地址:https://www.cnblogs.com/Glacier-elk/p/11668114.html
Copyright © 2020-2023  润新知