• BZOJ 2750: [HAOI2012]Road( 最短路 )


    对于每个点都跑最短路, 然后我们得到了个DAG, 在这DAG上更新每条边的答案.

    考虑e(u, v)∈DAG对答案的贡献:  假设从S到u得路径数为A[u], 从v出发到达任意点的路径数为B[v], 那么e(u, v)的答案可以加上A[u] * B[v](显然).

    A可以按拓扑序递推得到, B可以通过记忆化搜索得到, 都是O(m). 所以总时间复杂度O(nmlogn + nm)

    -------------------------------------------------------------------------------------

    #include<bits/stdc++.h>
      
    #define rep(i, n) for(int i = 0; i < n; i++)
    #define clr(x, c) memset(x, c, sizeof(x))
    #define REP(x) for(edge* e = head[x]; e; e = e->next)
    #define foreach(e, x) for(__typeof(x.begin()); e != x.end(); e++)
    #define mod(x) ((x) %= MOD)
     
    using namespace std;
     
    const int maxn = 1509, maxm = 5009;
    const int MOD = 1000000007;
     
    struct edge {
    int to, w, num;
    edge* next;
    } E[maxm], *pt = E, *head[maxn];
     
    inline void addedge(int u, int v, int d, int _) {
    pt->to = v, pt->w = d, pt->num = _;
    pt->next = head[u];
    head[u] = pt++;
    }
     
    struct node {
    int x, w;
    bool operator < (const node &t) const {
    return w > t.w;
    }
    };
     
    int d[maxn], cnt[maxn], ans[maxm], A[maxn], B[maxn], n;
     
    void dijkstra(int S) {
    rep(i, n) d[i] = MOD;
    d[S] = 0;
    priority_queue<node> Q;
    Q.push( (node) {S, 0} );
    while(!Q.empty()) {
    node t = Q.top(); Q.pop();
    if(d[t.x] != t.w) continue;
    REP(t.x) if(d[t.x] + e->w < d[e->to]) {
    d[e->to] = d[t.x] + e->w;
    Q.push( (node) {e->to, d[e->to]} );
    }
    }
    }
     
    // get B
    int dp(int x) {
    if(B[x]) return B[x];
    REP(x) if(d[e->to] == d[x] + e->w)
       mod(B[x] += dp(e->to));
    return ++B[x];
    }
     
    //get A
    void DFS(int x) {
    REP(x) if(d[e->to] == d[x] + e->w) {
    mod(A[e->to] += A[x]);
    if(!--cnt[e->to]) DFS(e->to);
    }
    }
     
    void dfs(int x) {
    REP(x) if(d[e->to] == d[x] + e->w)
    if(!cnt[e->to]++) dfs(e->to);
    }
     
    void work(int x) {
    dijkstra(x);
    clr(cnt, 0), clr(A, 0), clr(B, 0);
    dfs(x), dp(x), A[x] = 1, DFS(x);
    rep(i, n)
       REP(i) if(d[i] + e->w == d[e->to])
           mod(ans[e->num] += 1LL * A[i] * B[e->to] % MOD);
    }
     
    inline int read() {
    char c = getchar();
    for(; !isdigit(c); c = getchar());
    int ans = 0;
    for(; isdigit(c); c = getchar())
       ans = ans * 10 + c - '0';
    return ans;
    }
     
    int main() {
    freopen("test.in", "r", stdin);
    int m;
    clr(head, 0), clr(ans, 0);
    cin >> n >> m;
    rep(i, m) {
    int u = read() - 1, v = read() - 1, w = read();
    addedge(u, v, w, i);
    }
    rep(i, n) work(i);
    for(int* t = ans; t != ans + m; t++)
       printf("%d ", *t);
    return 0;
    }

    -------------------------------------------------------------------------------------

    2750: [HAOI2012]Road

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 356  Solved: 163
    [Submit][Status][Discuss]

    Description

    C国有n座城市,城市之间通过m条单向道路连接。一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小。两条最短路不同,当且仅当它们包含的道路序列不同。我们需要对每条道路的重要性进行评估,评估方式为计算有多少条不同的最短路经过该道路。现在,这个任务交给了你。

    Input

    第一行包含两个正整数n、m
    接下来m行每行包含三个正整数u、v、w,表示有一条从u到v长度为w的道路

    Output

    输出应有m行,第i行包含一个数,代表经过第i条道路的最短路的数目对1000000007取模后的结果

    Sample Input

    4 4
    1 2 5
    2 3 5
    3 4 5
    1 4 8

    Sample Output

    2
    3
    2
    1

    HINT

    数据规模

    30%的数据满足:n≤15、m≤30

    60%的数据满足:n≤300、m≤1000

    100%的数据满足:n≤1500、m≤5000、w≤10000

    Source

  • 相关阅读:
    蛇形填数(算法竞赛入门经典)
    35. Search Insert Position(LeetCode)
    70. Climbing Stairs(LeetCode)
    循环结构程序设计(算法竞赛入门经典)课后题
    阶乘之和(算法竞赛入门经典)[求余问题]
    有关int范围的例题(算法竞赛入门经典)
    矩阵行成列,列成行
    543. Diameter of Binary Tree(LeetCode)
    415. Add Strings(LeetCode)
    121. Best Time to Buy and Sell Stock(LeetCode)
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4671927.html
Copyright © 2020-2023  润新知