• 【题解】Atcoder ARC#90 E-Avoiding Collision


      自己做出来固然开心,但是越发感觉到自己写题的确是很慢很慢了……往往有很多的细节反反复复的考虑才能确定,还要加油呀~

      这道题目的突破口在于正难则反。直接求有多少不相交的不好求,我们转而求出所有相交的。我们先预处理出由 (S) 到 (T) 的最短路图(跑一边Dijkstra,所有的最短路径构成的图),显然可以顺便处理出 (T) 到 (S) 的。然后这个图是一个拓扑图,满足的性质就是从 (S) 点出发的任意一条路径终点均为 (T) 且为二者之间的最短路。拓扑图dp对于每个点我们又可以获得  (Way1[u],  Way2[u]) 分别表示从起点到 (u) 点的总路径数和从终点到 (u) 的总路径数。

      之后我们可以分类讨论一下,两条路径相遇是相遇在点上还是相遇在边上。相遇在点上很好判断,就是从起点到 (u) 点的距离正好等于从 (u) 点到终点的距离;相遇在边上则要求路径的终点落在这条边上,也是可以 O(1) 判断的。这样就好啦~(๑´ㅂ`๑)

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 500000
    #define mod 1000000007
    #define int long long
    int n, m, dis1[maxn], dis2[maxn];
    int ans, K, S, T, Way1[maxn], Way2[maxn];
    bool vis[maxn];
    
    int read()
    {
        int x = 0, k = 1;
        char c; c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    struct edge
    {
        int cnp, fr[maxn], to[maxn], co[maxn];
        int last[maxn], head[maxn], degree[maxn];
        edge() { cnp = 2; }
        void add(int u, int v, int w = 0)
        { 
            fr[cnp] = u, to[cnp] = v, co[cnp] = w;
            last[cnp] = head[u], head[u] = cnp ++; 
        }
    }E[2], G;
    
    struct node
    {
        int x, y;
        node(int _x = 0, int _y = 0) { x = _x, y = _y; }
        friend bool operator <(const node& a, const node& b)
        { return a.y > b.y; }
    }; priority_queue <node> q;
    
    void Up(int &x, int y) { x = (x + y) % mod; }
    int Qpow(int x) { return x * x % mod; }
    void Dijk(int S, int *dis)
    {
        memset(vis, 0, sizeof(vis));
        dis[S] = 0; q.push(node(S, 0));
        while(!q.empty())
        {
            node now = q.top(); q.pop();
            int u = now.x; if(vis[u]) continue; vis[u] = 1;
            for(int i = G.head[u]; i; i = G.last[i])
            {
                int v = G.to[i];
                if(dis[v] > dis[u] + G.co[i])
                {
                    dis[v] = dis[u] + G.co[i];
                    q.push(node(v, dis[v]));
                }
            }
        }
    }
    
    void Toposort()
    {
        memset(vis, 0, sizeof(vis));
        queue <int> q; q.push(S);
        while(!q.empty())
        {
            int u = q.front(); q.pop();
            for(int i = G.head[u]; i; i = G.last[i])
            {
                int v = G.to[i];
                if((dis1[u] + dis2[v] + G.co[i]) == K)
                {
                    E[0].add(u, v); E[0].degree[v] ++;
                    E[1].add(v, u); E[1].degree[u] ++;
                    if(!vis[v]) q.push(v), vis[v] = 1;
                }
            }
        }
    }
    
    void TopoDP(int opt, int *Way)
    {
        queue <int> q;
        for(int i = 1; i <= n; i ++) 
            if(!E[opt].degree[i]) 
                q.push(i), Way[i] = 1;
        while(!q.empty())
        {
            int u = q.front(); q.pop(); 
            for(int i = E[opt].head[u]; i; i = E[opt].last[i])
            {
                int v = E[opt].to[i];
                E[opt].degree[v] --; Up(Way[v], Way[u]);
                if(!E[opt].degree[v]) q.push(v);
            }
        }
    }
    
    signed main()
    {
        n = read(), m = read(); S = read(), T = read();
        for(int i = 1; i <= m; i ++) 
        {
            int x = read(), y = read(), w = read();
            G.add(x, y, w), G.add(y, x, w);
        }
        memset(dis1, 127, sizeof(dis1)); memset(dis2, 127, sizeof(dis2)); 
        Dijk(S, dis1), Dijk(T, dis2);
        K = dis1[T]; Toposort(); 
        TopoDP(0, Way1); TopoDP(1, Way2);
        for(int i = 1; i <= n; i ++)
            if(dis1[i] + dis1[i] == K) 
                Up(ans, Qpow(Way1[i] * Way2[i] % mod) % mod);
        for(int i = 2; i < E[1].cnp; i ++)
        {
            int u = E[0].fr[i], v = E[0].to[i];
            if(dis1[u] * 2 == K || dis1[v] * 2 == K) continue;
            if(K > 2 * dis1[u] && K < 2 * (K - dis2[v])) 
                Up(ans, Qpow(Way1[u] * Way2[v] % mod) % mod);
        }
        ans = (Way1[T] * Way1[T] % mod - ans + mod) % mod;
        printf("%lld
    ", ans);
        return 0;
    }
  • 相关阅读:
    1、SASS / SCSS 总结简介
    Chrome 中的 JavaScript 断点设置和调试技巧
    《Javascript 设计模式》-读书笔记
    CSS基线之道
    高性能 CSS3 动画
    《编写高质量代码》web前端开发修炼之道-读书笔记
    《Effective JavaScript》编写高质量的Javascript代码的68个有效方法-读书笔记
    Sea.js-模块化开发框架
    JSLine和JSHint代码质量检查工具和uglifyjs压缩JS的
    在Windows平台上安装Node.js及NPM模块管理
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/9733849.html
Copyright © 2020-2023  润新知