zoukankan      html  css  js  c++  java
  • [HAOI 2012] Road

    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=2750

    [算法]

            考虑计算每个点对每条边的贡献

            对于每个点首先运行SPFA或Dijkstra单源最短路 , 建出以该点为根的最短路树(图)

            由于最短路图是一个DAG(有向无环图) , 我们可以求出其拓扑序列 , 对于每个点i , 计算 :

            CNT1 : 从枚举的点到该点的 , 最短路图上的路径条数

            CNT2 : 从该点出发 , 在最短路图上 , 有多少条路径

            对于每条在最短路图上的边 , 用乘法原理计算贡献即可

            时间复杂度 : O(NM)

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int N = 5010;
    const int inf = 2e9;
    const int P = 1e9 + 7;
    
    struct edge
    {
            int to , w , nxt;
    } e[N << 1];
    
    int n , m , tot;
    int dist[N] , cnta[N] , cntb[N] , u[N] , v[N] , w[N] , head[N] , topo[N] , ans[N];
    bool ok[N];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void addedge(int u , int v , int w)
    {
            ++tot;
            e[tot] = (edge){v , w , head[u]};
            head[u] = tot;
    }
    inline void spfa(int S)
    {
            static bool inq[N];
            queue< int > q;
            for (int i = 1; i <= n; ++i)
            {
                    dist[i] = inf;
                    inq[i] = false;
                    cnta[i] = cntb[i] = 0;
            }
            for (int i = 1; i <= m; ++i) ok[i] = false;
            q.push(S);
            inq[S] = true;
            dist[S] = 0;
            while (!q.empty())
            {
                    int cur = q.front();
                    q.pop();
                    inq[cur] = false;
                    for (int i = head[cur]; i; i = e[i].nxt)
                    {
                            int v = e[i].to , w = e[i].w;
                            if (dist[cur] + w < dist[v])
                            {    
                                    dist[v] = dist[cur] + w;
                                    if (!inq[v])
                                    {
                                            inq[v] = true;
                                            q.push(v);
                                    }
                            } 
                    }
            }
            for (int i = 1; i <= m; ++i)
                    if (dist[u[i]] + w[i] == dist[v[i]]) ok[i] = true;
    } 
    inline void calc()
    {
            queue< int > q;
            static int deg[N];
            for (int i = 1; i <= n; ++i)
                    deg[i] = 0;
            for (int i = 1; i <= m; ++i)
                    if (ok[i]) ++deg[v[i]];
            for (int i = 1; i <= n; i++)
                    if (!deg[i]) 
                    {
                            cnta[i] = 1;
                            q.push(i);
                    }
            int M = 0;
            while (!q.empty())
            {
                    int cur = q.front();
                    q.pop();
                    topo[++M] = cur;
                    for (int i = head[cur]; i; i = e[i].nxt)
                    {
                            int v = e[i].to;
                            if (!ok[i]) continue;
                            cnta[v] = (cnta[v] + cnta[cur]) % P;
                            if (!(--deg[v])) q.push(v);
                    }
            }
            for (int i = n; i >= 1; i--)
            {
                    ++cntb[topo[i]];
                    for (int j = head[topo[i]]; j; j = e[j].nxt)
                    {
                            int v = e[j].to;
                            if (!ok[j]) continue;
                            cntb[topo[i]] = (cntb[topo[i]] + cntb[v]) % P;
                    }
            }
    }
    inline void update(int S)
    {
            spfa(S);
            calc();
            for (int i = 1; i <= m; ++i)
                    if (ok[i]) ans[i] = (ans[i] + 1ll * cnta[u[i]] * cntb[v[i]] % P) % P;        
    }
    
    int main()
    {
            
            read(n); read(m);
            for (int i = 1; i <= m; ++i)
            {
                    read(u[i]); read(v[i]); read(w[i]);
                    addedge(u[i] , v[i] , w[i]);
            }
            for (int i = 1; i <= n; ++i) update(i);
            for (int i = 1; i <= m; ++i) printf("%d
    " , ans[i]);
            
            return 0;
        
    }
  • 相关阅读:
    转:JMeter5的If Controller操作解析
    .NET Core优秀的应用逻辑分层框架设计
    socket阻塞导致拿不到信息
    2018年开始了,我们还是说说2017吧
    PHP 学习 遇到坑的第一章
    记一次高并发情况,服务器和代码修改过程记录。
    IIS 提高连接的并发数,和CPU的使用率。
    2017年总结
    在 safari 浏览器 onclick 出现延迟的现象
    微信JS-api 注意事项
  • 原文地址:https://www.cnblogs.com/evenbao/p/10540041.html
Copyright © 2011-2022 走看看