• P1875 佳佳的魔法药水


    P1875 佳佳的魔法药水

    题意

    现在一共有n个点,每个点都有一个代价,接下来告诉你多组a、b、c,表示,通过a、b可以到达c,可能会存在自环,现在问你到达一号点的最小的代价,并且这个代价有多少条方案。

    思路

    在这里插入图片描述
    流汗黄豆。。。。。
    Dijkstra
    我们现在知道没个点的代价,我们可以选择任意的两个点开始进入,或者直接选择1号点(但是代价可能会很大),其实它的本质还是最短路,只不过这里是要选择两个点罢了,这里的代价相当于就是边权,我们假设一个不存在的点(在路径外面),我们现在要从这个点到达1号点,要求是路径最短,那么就是一个最短路,我们最开始知道这个点到每个点的路径花费,那么我们直接存入优先队列中,后面直接是dijstra了,我们每次从花费最小的入手,现在想一下我们能够到达下一个点的条件是啥?
    是不是两个点的最短路径都已经更新过才行,因为我们要更新一个点,那么只有当能够到达它的两个点的最短路都已经被更新过了才能实现,那么我们花费的问题解决了,现在来想一下方案数,这里要分两种情况,1、当这个点需要更新,那么这个点的方案数是将会被覆盖的,所以直接是能够到达它的两个点的方案数的乘积,2、当前点的最短路径恰好等于两个点能够到达它的最短路,这个时候就是累加了。

    #include 
    
    #define int long long
    
    using namespace std;
    
    const int N = 1e3 + 10, M = N * N, inf = 0x3f3f3f3f;
    typedef pair<int, int> PII;
    
    int e[M], w[M], ne[M], h[M], idx;
    
    int dis[N], cnt[N];
    bool st[N];
    
    priority_queue<PII, vector<PII>, greater<PII>> q;
    
    void add(int a, int b, int c) { e[idx] = b; w[idx] = c; ne[idx] = h[a]; h[a] = idx ++; }
    
    void dijkstra()
    {
        memset(st, 0, sizeof st);
    
        while (!q.empty())
        {
            auto u = q.top(); q.pop();
            int ver = u.second, distance = u.first;
    
            if (distance != dis[ver]) continue;
            if (st[ver]) continue;
            st[ver] = 1;
    
            for (int i = h[ver]; i != -1; i = ne[i])
            {
                int x = e[i], v = w[i];
    
                if (st[x])
                {
                    if (dis[v] > distance + dis[x])
                    {
                        dis[v] = distance + dis[x];
                        cnt[v] = cnt[ver] * cnt[x];
                        q.push({dis[v], v});
                    }
                    else if (dis[v] == distance + dis[x])
                        cnt[v] += cnt[ver] * cnt[x];
                }
            }
        }
    
    }
    
    void solve()
    {
        int n; scanf("%lld", &n);
        memset(h, -1, sizeof h);
        for (int i = 1; i <= n; i ++)
        {
            cin >> dis[i];
            cnt[i] = 1;
            q.push({dis[i], i});
        }
    
        int x, y, z;
        while (scanf("%lld%lld%lld", &x, &y, &z) != EOF)
        {
            add(x + 1, y + 1, z + 1);
            if (x + 1 == y + 1) continue;
            add(y + 1, x + 1, z + 1);
        }
    
        dijkstra();
    
        printf("%lld %lld\n", dis[1], cnt[1]);
    }
    
    signed main()
    {
        solve();
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
  • 相关阅读:
    GOPATH和Go Modules
    机器学习模型常用评价指标(Accuracy, Precision, Recall、F1-score、MSE、RMSE、MAE、R方)
    两个node服务共同修改一个计数文件,互相监控服务是否停止
    解析正则表达式的语法(二)
    【Java数据类型】
    监控服务器体系
    具有生物活性的天然产物——雷公藤
    编程语言“鄙视链” +1?亚马逊力捧 Rust,Go 技术负责人连发 14 条推特抵制“拉踩”
    批量加载excel的xsl文件到hive分区表
    LuatOS-SOC接口文档(air780E)-- ftp - ftp 客户端
  • 原文地址:https://blog.csdn.net/MagicFromMe/article/details/126065422