• 牛客网:雪拉比的求救(最短路计数)


    链接:https://ac.nowcoder.com/acm/contest/7293/I
    来源:牛客网

    题目描述

    爱与正义的火箭队为了得到雪拉比,于是对它展开了捕捉计划。当雪拉比受到伤害时,它会使用全部能力穿越到1小时之后的时间,并发出了SOS的求救。
    小梁在旅行的途中感受到了雪拉比的求救,她跟着雪拉比的求救,来到了一座遗迹,该遗迹的俯视图可看为n ext{n}n个传送点,m ext{m}m条道路所组成的双向连通图,每一条道路都有对应的长度di ext{d}_idi
    通过心灵指引小梁终于救出了雪拉比。但是由于被火箭队追赶,雪拉比只能隐藏自己的气息。
    火箭队也发现了雪拉比和小梁的位置,同时小梁也在雪拉比的帮助下确定了火箭队的位置。小梁想知道在她和火箭队移动速度相同的条件下,为了顺利的躲避火箭队,并且双方都以最短路径向对方原始位置移动,有多少方案可以使得他们不相遇,并对方案数取模109+710^9+7109+7。
     

    题解:

    //由于双方只会选择最短路
    //先处理出每个点到s的最短路距离和到t的最短路距离
    //每个点到s的最短路数量和到t的最短路数量
    //如果两个距离之和不等于s到t的最短路,就不算贡献
    //如果在点上相遇
    //需要满足这个点两边的最短路长度相同
    //答案是两边的最短路数量平方的乘积
    //如果在边上相遇
    //枚举每个点和它的令接点
    //如果这个点到s的最短路加上这个点到t的最短路的和加上这条边的边权等于st的最短路
    //再看这两条路径的差是否小于等于这条边权
    //如果前面条件全都符合,对答案的贡献是两边最短路数量平方的乘积
    
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+100;
    const int mod=1e9+7;
    const ll inf=1e18;
    int n,m,s,t;
    struct node {
        int u,v,w,nxt;
    }edge[maxn*4];
    int head[maxn];
    int tot;
    void addedge (int u,int v,int w) {
        edge[tot].u=u;
        edge[tot].v=v;
        edge[tot].w=w;
        edge[tot].nxt=head[u];
        head[u]=tot++;
        
    } 
    ll d[2][maxn];
    ll cnt[2][maxn];
    int vis[maxn];
    struct qnode {
        ll v;
        ll w;
        bool operator < (const qnode &r) const {
            return w>r.w;
        }
        qnode (int vv,ll ww) {
            v=vv;
            w=ww;
        }
    };
    void dij (int s,int f) {
        for (int i=0;i<maxn;i++) d[f][i]=inf,vis[i]=0;
        priority_queue<qnode> q;
        d[f][s]=0;
        cnt[f][s]=1;
        q.push(qnode(s,0));
        while (!q.empty()) {
            qnode tt=q.top();
            q.pop();
            int u=tt.v;
            if (vis[u]) continue;
            vis[u]=1;
            for (int i=head[u];i!=-1;i=edge[i].nxt)    {
                int v=edge[i].v;
                int w=edge[i].w;
                if (d[f][v]>d[f][u]+w) {
                    d[f][v]=d[f][u]+w;
                    cnt[f][v]=cnt[f][u];
                    q.push(qnode(v,d[f][v]));
                }
                else if (d[f][v]==d[f][u]+w) 
                    cnt[f][v]=(cnt[f][v]+cnt[f][u])%mod;
            }
        }
    }
    int main () {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) head[i]=-1;
        tot=0;
        scanf("%d%d",&s,&t);
        for (int i=1;i<=m;i++) {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        dij(s,0);
        dij(t,1);
        ll ans=cnt[0][t]%mod*cnt[0][t]%mod;
        ans%=mod;
        for (int i=1;i<=n;i++) {
            if (d[0][i]+d[1][i]!=d[0][t]) continue;
            if (d[0][i]!=d[1][i]) continue;
            ans-=(cnt[0][i]*cnt[1][i]%mod)*(cnt[0][i]*cnt[1][i]%mod)%mod;
            ans=(ans+mod)%mod;
        }
        for (int i=1;i<=n;i++) {
            for (int j=head[i];j!=-1;j=edge[j].nxt) {
                int v=edge[j].v;
                int u=i;
                //printf("%lld
    ",d[0][u]+d[1][v]+edge[j].w);
                if (d[0][u]+d[1][v]+edge[j].w!=d[0][t])
                    continue;
                if (d[0][u]*2<d[0][t]&&d[1][v]*2<d[0][t])
                    ans-=(cnt[0][u]*cnt[1][v]%mod)*(cnt[0][u]*cnt[1][v]%mod)%mod,
                    ans=(ans+mod)%mod;
            }
        }
        //printf("%lld
    ",cnt[0][t]*cnt[0][t]);
        printf("%lld
    ",ans);
        
    }
  • 相关阅读:
    Android ViewPager用法小结
    HDU1212 Big Number 【同余定理】
    1051. Pop Sequence (25)
    FFmpeg源码结构图
    oracle访问不同用户的表不添加用户名前缀
    window7开启Administrator账户
    Window下对nodejs多版本管理GNVM
    基于Centos7.5搭建Docker环境
    grep与孪生兄弟egrep差异
    Linux编译步骤概述
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13560204.html
Copyright © 2020-2023  润新知