zoukankan      html  css  js  c++  java
  • [无聊测试赛] T12 道路

    by _Zhumingrui

    这道题的大致题意是:根据最短路求边的拓扑图,然后求出每个边的入度。
    我用 Dijkstra 求最短路,顺便建好图。之后使用 BFS 来递推拓扑条件,保存至 ans 数组。

    注意事项

    使用 long long,你们懂得。

    这个做法需要倒序遍历边,因为只有倒序遍历能满足拓扑序。

    本代码需要 (O_2) 优化 才可通过本题。

    Code:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    using namespace std;
    namespace {
    constexpr const int N = 2333;
    constexpr int M = 5555;
    unsigned mod = 1000000007;
    //vector清空边不容易,用前向星快好多
    struct {
        struct {
            int v, n, w;
        }edge[M];
        int link[N], cnt;
        inline void add(const int& u, const int& v, const int& w) {
            edge[++cnt].w = w;
            edge[cnt].v = v;
            edge[cnt].n = link[u];
            link[u] = cnt;
        }
    }a, b; //建两个图,一个(A)是原图,另一个(B)是DAG 
    int n, m;
    struct ___ {
        int w, v;
        inline bool operator <(const ___& b) const {
            return w > b.w;
        }
    };
    priority_queue<___> heap;
    queue<int> q;
    int d[N];
    bool book[N];
    int rrank[N];
    long long dp[N], ans[M], dp1[N];
    inline void dijkstra(const int& s) {
        b.cnt = 0;
        for (int i = 1; i <= n; i++) {
            d[i] = 0x3f3f3f3f;
            book[i] = false;
            dp[i] = 1;
            rrank[i] = 0;
            b.link[i] = 0;
            dp1[i] = 0;
        }
        d[s] = 0;
        dp1[s] = 1;
        heap.push({ 0,s });
        while (!heap.empty()) {
            int now = heap.top().v;
            heap.pop();
            if (book[now])continue;
            book[now] = true;
            //倒着推
            int nxt = a.link[now];
            while (nxt) {
                const int& v = a.edge[nxt].v;
                const int& val = a.edge[nxt].w;
                if (!book[v]) {
                    //如果相等,加上一条
                    if (d[v] == d[now] + val) {
                        b.add(v, now, nxt);
                        dp1[v] = (dp1[v] + dp1[now]) % mod;
                    }
                    //如果更好,就把边拆了,重新加上条
                    if (d[v] > d[now] + val) {
                        b.link[v] = 0;
                        b.add(v, now, nxt);
                        dp1[v] = dp1[now];
                        d[v] = d[now] + val;
                        heap.push({ d[v], v });
                    }
                }
                nxt = a.edge[nxt].n;
            }
        }
    }
    inline void toposort() {
        //求入度
        for (int i = 1; i <= n; i++)
            for (int p = b.link[i]; p; p = b.edge[p].n)
                rrank[b.edge[p].v]++;
        for (int i = 1; i <= n; i++)
            if (rrank[i] == 0)
                q.push(i);
        //递推
        while (!q.empty()) {
            int now = q.front();
            q.pop();
            int nxt = b.link[now];
            while (nxt) {
                const int& v = b.edge[nxt].v;
                const int& w = b.edge[nxt].w;
                dp[v] = (dp[v] + dp[now]) % mod;
                ans[w] = (ans[w] + dp[now] * dp1[v]) % mod;
                rrank[v]--;
                if (rrank[v] == 0)
                    q.push(v);
                nxt = b.edge[nxt].n;
            }
        }
    }
    int u, v, w;
    inline int get() {
        static unsigned char a;
        static char st[100], eof;
        if (a == 100 || a == 0)
            if (!eof) {
                if (fread(st, sizeof(char), 100, stdin) < 100)
                    eof = 1;
                a = 0;
            }
            else {
                return -1;
            }
        return st[a++];
    }
    #ifdef  _DEBUG
    #define get() getchar()
    #endif
    inline void read(int& ans) {
        ans = 0x00000000;
        char ch = get();
        while ((ch < '0') || (ch > '9'))ch = get();
        while ((ch >= '0') && (ch <= '9')) {
            ans = (ans << 3) + (ans << 1) + (ch & 15);
            ch = get();
        }
    }
    }
    int main() {
    #define int register int
    read(n), read(m);
    for (int i = 1; i <= m; i++) {
        read(u), read(v), read(w);
        a.add(u, v, w);
    }
    for (int i = 1; i <= n; i++) {
        dijkstra(i);
        toposort();
    }
    for (int i = 1; i <= m; i++)
        printf("%d
    ", ans[i]);
    return 0;
    #undef int
    }
    
  • 相关阅读:
    i3wm 入门
    install kali on my x200
    Linux下pn532板子测试学校水卡
    Linux下常用工具
    未能加载文件或程序集"Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad
    SqlServer 日期函数
    asp.net 网站部署出错-未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序
    win7中未加载类型“System.ServiceModel.Activation.HttpModule”
    ASP.NET开发工具用到的密匙与注意事项
    TCP/TP 三次握手
  • 原文地址:https://www.cnblogs.com/DannyXu/p/12539203.html
Copyright © 2011-2022 走看看