zoukankan      html  css  js  c++  java
  • 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;
    }
    

  • 相关阅读:
    [ jquery 选择器 :hidden ] 此方法选取匹配所有不可见元素,或者type为hidden的元素
    剑指 Offer 03. 数组中重复的数字 哈希
    LeetCode 1736. 替换隐藏数字得到的最晚时间 贪心
    Leetcode 1552. 两球之间的磁力 二分
    Leetcode 88. 合并两个有序数组 双指针
    LeetCode 1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?
    LeetCode 1743. 相邻元素对还原数组 哈希
    LeetCode 1745. 回文串分割 IV dp
    剑指 Offer 47. 礼物的最大价值 dp
    剑指 Offer 33. 二叉搜索树的后序遍历序列 树的遍历
  • 原文地址:https://www.cnblogs.com/Glacier-elk/p/11668114.html
Copyright © 2011-2022 走看看