• AtCoder ARC 090 E / AtCoder 3883: Avoiding Collision


    题目传送门:ARC090E

    题意简述:

    给定一张有 (N) 个点 (M) 条边的无向图。每条边有相应的边权,边权是正整数。

    小 A 要从结点 (S) 走到结点 (T) ,而小 B 则相反,他要从结点 (T) 走到结点 (S) 。

    小 A 和小 B 走一条边需要的时间都是这条边的边权,不论方向。

    问有多少种走法,使得他们俩都走了最短路,但是他们不会相遇,这里相遇指的是在点上或者在边上相遇。

    答案对 (10^9+7) 取模。

    题解:

    用 Dijkstra 算法求出以结点 (S) 和结点 (T) 出发到每个点的最短路和最短路条数。

    把从结点 (S) 到结点 (i) 的最短路记作 (d1_i) ,最短路条数对 (10^9+7) 取模的结果记作 (g1_i)。

    把从结点 (T) 到结点 (i) 的最短路记作 (d2_i) ,最短路条数对 (10^9+7) 取模的结果记作 (g2_i)。

    把从结点 (S) 到结点 (T) 的最短路记作 (Dist) 。

    考虑用容斥的方法计算答案。答案等于总方案数减去相遇的方案数。总方案数为 (g1_T^2) 。

    因为走的都是最短路,而且边权是正的,不难证明两人只会相遇一次。

    所以只要统计在每个点或者每条边经过的方案数即可。

    考虑经过结点 (i) 的方案数:
    前提是 (d1_i+d2_i=Dist) 且 (d1_i=d2_i) ,方案数为 (g1_i^2g2_i^2) 。

    考虑经过边 (ioverset{d}{Longleftrightarrow}j) (其中小 A 从结点 (i) 走向结点 (j) )的方案数:
    前提是 (d1_i+d+d2_i=Dist) 且 (d1_i+d>d2_j) 且 (d1_i<d+d2_j) ,方案数为 (g1_i^2g2_j^2) 。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=(a);i<=(b);++i)
     3 #define eF(i,u) for(int i=h[u];i;i=nxt[i])
     4 #define Mod 1000000007
     5 using namespace std;
     6 typedef long long ll;
     7 typedef pair<ll,int> pli;
     8 
     9 int n,m,S,T;
    10 ll Ans;
    11 int U[200001],V[200001],D[200001];
    12 int h[100001],nxt[400001],to[400001],w[400001],tot;
    13 void ins(int x,int y,int z){nxt[++tot]=h[x];to[tot]=y;w[tot]=z;h[x]=tot;}
    14 
    15 ll d1[100001],d2[100001],g1[100001],g2[100001];bool v1[100001],v2[100001];
    16 priority_queue<pli,vector<pli>,greater<pli> > pq;
    17 
    18 void Dij(ll*d,ll*g,bool*v,int s){
    19     d[s]=0ll;
    20     pq.push(pli(0ll,s));
    21     g[s]=1;
    22     while(!pq.empty()){
    23         pli P=pq.top(); pq.pop();
    24         int u=P.second; ll du=P.first;
    25         if(v[u]||d[u]<du) continue;
    26         v[u]=1;
    27         eF(i,u){
    28             if(d[to[i]]==du+w[i])
    29                 g[to[i]]=(g[to[i]]+g[u])%Mod;
    30             if(d[to[i]]>du+w[i])
    31                 g[to[i]]=g[u],
    32                 d[to[i]]=du+w[i], pq.push(pli(d[to[i]],to[i]));
    33         }
    34     }
    35 }
    36 
    37 int main(){
    38     int x,y,z;
    39     scanf("%d%d",&n,&m);
    40     scanf("%d%d",&S,&T);
    41     F(i,1,m) scanf("%d%d%d",&x,&y,&z), ins(x,y,z), ins(y,x,z), U[i]=x, V[i]=y, D[i]=z;
    42     memset(d1,0x3f,sizeof d1);
    43     Dij(d1,g1,v1,S);
    44     memset(d2,0x3f,sizeof d2);
    45     Dij(d2,g2,v2,T);
    46     ll Dist=d1[T];
    47     Ans=g1[T]*g1[T]%Mod;
    48     F(i,1,n){
    49         if(d1[i]+d2[i]==Dist&&d1[i]==d2[i])
    50             Ans=(Ans-g1[i]*g1[i]%Mod*g2[i]%Mod*g2[i]%Mod)%Mod;
    51     }
    52     int u,v,d;
    53     F(i,1,m){
    54         u=U[i], v=V[i], d=D[i];
    55         if(d1[u]+d+d2[v]==Dist && d1[u]+d>d2[v] && d2[v]+d>d1[u]){
    56             Ans=(Ans-g1[u]*g2[v]%Mod*g1[u]%Mod*g2[v]%Mod)%Mod;
    57         }
    58         u=V[i], v=U[i], d=D[i];
    59         if(d1[u]+d+d2[v]==Dist && d1[u]+d>d2[v] && d2[v]+d>d1[u]){
    60             Ans=(Ans-g1[u]*g2[v]%Mod*g1[u]%Mod*g2[v]%Mod)%Mod;
    61         }
    62     }
    63     printf("%lld",(Ans%Mod+Mod)%Mod);
    64     return 0;
    65 }
  • 相关阅读:
    tomcat加载项目原理解惑
    英语口语大全
    ubuntu中wubi正在下载ubuntu11.04desktopi386.iso
    Strust2获得session和request
    字符串转成对象
    DevExpress控件使用
    DevExpress控件之GridControl控件(控件篇)
    ASP.NET AJAX + JSON 实现对象调用
    WinForm窗体之间交互的一些方法[转]
    barmanager设置
  • 原文地址:https://www.cnblogs.com/PinkRabbit/p/10022225.html
Copyright © 2020-2023  润新知