zoukankan      html  css  js  c++  java
  • 常州模拟赛d5t1 journalist

    分析:出题人丧心病狂卡spfa......只能用dijkstar+堆优化.

          主要的难点是字典序的处理上,一个想法是在做最短路的时候处理,边松弛边记录,比个大小记录最佳答案.具体的思路大概和最短路计数差不多,当遇到d[u] + w[i] == d[v]是,说明到d[v]有两条最短路了,更新一下答案。

          但是这样效率太低了,每一次松弛都要更新一次,能不能一次性更新完呢?可以的.我们在跑完最短路后把满足d[u] + w[i] == d[v]的点v加入u的邻接表中,排个序,然后dfs一遍就好了.

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <cmath>
    #include <queue>
    #include <vector>
    
    using namespace std;
    
    const long long inf = 1e15;
    
    struct node
    {
        long long len;
        int x;
    };
    
    bool operator < (node a, node b)
    {
        return a.len > b.len;
    }
    
    int n, m,b[200010],head[200010],to[400010],nextt[400010],tot = 1,w[400010],vis[200010];
    int u[400010], v[400010], z[400010],ans[200010];
    long long d[200010];
    vector <int> a[200010];
    
    void add(int x, int y, int z)
    {
        w[tot] = z;
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    void dijkstar()
    {
        d[1] = 0;
        priority_queue <node> q;
        node t;
        t.len = 0;
        t.x = 1;
        q.push(t);
        while (!q.empty())
        {
            while (!q.empty() && vis[q.top().x])
                q.pop();
            if (q.empty())
                break;
            node u = q.top();
            q.pop();
            long long len = u.len;
            int x = u.x;
            vis[x] = 1;
            for (int i = head[x]; i;i = nextt[i])
            {
                int v = to[i];
                if (len + w[i] < d[v])
                {
                    d[v] = len + w[i];
                    node temp;
                    temp.len = d[v];
                    temp.x = v;
                    q.push(temp);
                }
            }
        }
    }
    
    bool cmp(int x, int y)
    {
        return b[x] < b[y];
    }
    
    void dfs(int depth, int x)
    {
        if (vis[x])
            return;
        vis[x] = 1;
        ans[depth] = x;
        if (x == n)
        {
            for (int i = 1; i <= depth; i++)
                printf("%d ", b[ans[i]]);
            printf("
    ");
            return;
        }
        for (int i = 0; i < a[x].size(); i++)
            dfs(depth + 1, a[x][i]);
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
            scanf("%d", &b[i]);
        for (int i = 1; i <= m; i++)
        {
            scanf("%d%d%d", &u[i], &v[i], &z[i]);
            add(u[i], v[i], z[i]);
        }
        for (int i = 1; i <= n; i++)
            d[i] = inf;
        dijkstar();
        printf("%lld
    ", d[n]);
        for (int i = 1; i <= m; i++)
            if (d[u[i]] + z[i] == d[v[i]])
                a[u[i]].push_back(v[i]);
        for (int i = 1; i <= n; i++)
            sort(a[i].begin(), a[i].end(), cmp);
        memset(vis, 0, sizeof(vis));
        dfs(1, 1);
    
        return 0;
    }
  • 相关阅读:
    实现input输入时智能搜索
    动态磁盘转基本磁盘(简单卷变为主分区)
    删掉一个文件夹相对于另一个文件夹多出的文件
    win10搜索不到蓝牙设备
    anaconda使用
    pycharm tab换为4个空格
    wamp端口冲突
    c++ 字符串
    pta 编程题20 旅游规划
    c++指针二维数组
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7427364.html
Copyright © 2011-2022 走看看