链接:https://ac.nowcoder.com/acm/contest/6106/I
来源:牛客网
题目描述
爱与正义的火箭队为了得到雪拉比,于是对它展开了捕捉计划。当雪拉比受到伤害时,它会使用全部能力穿越到1小时之后的时间,并发出了SOS的求救。
小梁在旅行的途中感受到了雪拉比的求救,她跟着雪拉比的求救,来到了一座遗迹,该遗迹的俯视图可看为n\text{n}n个传送点,m\text{m}m条道路所组成的双向连通图,每一条道路都有对应的长度di\text{d}_idi。
通过心灵指引小梁终于救出了雪拉比。但是由于被火箭队追赶,雪拉比只能隐藏自己的气息。
火箭队也发现了雪拉比和小梁的位置,同时小梁也在雪拉比的帮助下确定了火箭队的位置。小梁想知道在她和火箭队移动速度相同的条件下,为了顺利的躲避火箭队,并且双方都以最短路径向对方原始位置移动,有多少方案可以使得他们不相遇,并对方案数取模109+710^9+7109+7。输入描述:
第一行输入两个整数N和M(1≤N≤100000,1≤M≤200000) 第二行输入两个整数S和T(1≤S,T≤N,S≠T)分别表示小梁和火箭队所在的位置 下面M行输入三个整数 ui,vi,di表示第ui个点和第vi个点相连,他们的距离是di(1≤ui,vi≤N,1≤di≤10^9)输出描述:
输出所有符合条件的方案对10^9+7取模后的数。示例1
输入
8 9 4 2 1 2 2 7 6 9 2 8 12 4 2 18 8 4 2 3 5 18 1 5 3 4 7 7 2 7 7输出
2说明
4和2之间的最短路为14,其中不会相遇的方案路线分别为: ①T到S:2-8-4;S到T:4-7-2 ②T到S:2-7-4;S到T:4-8-2
思路:用dijkstra算法求解出,每个点到S的距离 da[0][i] 和到T的距离 da[1][i] ,以及相应的最短路线数 su[0][i] 和 su[1][i] 。
分析可知需要知道S到T的最短路径,以及路径数cnt=da[0][T]。
如果不考虑相遇则方案数为 sum=cnt*cnt 。
相遇的话则有两种情况:
1.在某一点相遇。方案数为 g=su[0][i]*su[1][i]*su[0][i]*su[1][i] 。
2.在路径上相遇。方案数为 h=su[0][u]*su[1][v]*su[0][u]*su[1][v] 。
最终结果为 sum-g-h 。
AC示例代码
#include <iostream>//超时 #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include <stack> #include <queue> #include <vector> #include <string> #define cla(a, sum) memset(a, sum, sizeof(a)) #define rap(i, m, n) for(int i=m; i<=n; i++) #define rep(i, m, n) for(int i=m; i>=n; i--) #define bug printf("???\n") using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<ll, int> P; const ll Inf = 1e17; const double eps = 1e-8; const int maxn = 1e5+5; const ll MOD=1e9+7; template <typename T> void read(T &x){ x = 0; int f = 1; char ch = getchar(); while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();} while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();} x *= f; } int n,m; int s,t; int a[maxn],cnt; struct node{ ll d; int id,next; }f[4*maxn]; int vis[2][maxn]={0}; ll da[2][maxn],su[2][maxn]; ll sum; void init(){ cla(a,-1); rap(i,0,n){ da[0][i]=da[1][i]=Inf; } cnt=0; } void add(int u,int v,ll d){ f[cnt].id =v; f[cnt].d =d; f[cnt].next =a[u]; a[u]=cnt++; } void dijk(int x,ll d[],int ok[],ll sa[]) { priority_queue<P>p; p.push(make_pair(0,x)); sa[x]=1;d[x]=0; while(!p.empty() ){ int u=p.top().second; p.pop() ; if(ok[u])continue; ok[u]=1; for(int i=a[u];i!=-1;i=f[i].next ){ int c=f[i].id ; if(d[c]>d[u]+f[i].d ){ d[c]=d[u]+f[i].d ; sa[c]=sa[u]%MOD; p.push(make_pair(-d[c],c)); }else if(d[c]==d[u]+f[i].d ){ sa[c]=(sa[u]+sa[c])%MOD; } } } } int main() { read(n);read(m); init(); cin>>s>>t; int u,v; ll d; rap(i,1,m){ scanf("%d%d%lld",&u,&v,&d); add(u,v,d); add(v,u,d); } dijk(s,da[0],vis[0],su[0]); dijk(t,da[1],vis[1],su[1]); sum=su[0][t]*su[1][s]%MOD; // cout<<sum<<endl; d=da[0][t]; rap(i,1,n){ if(da[0][i]==da[1][i]&&2*da[0][i]==d){//在某点相遇 sum=sum-(su[0][i]*su[1][i]%MOD)*(su[0][i]*su[1][i]%MOD)%MOD; sum=(sum+MOD)%MOD; } for(int k=a[i];k!=-1;k=f[k].next ){ u=f[k].id ; //在路径上相遇 ,注意d可能为奇数 if(da[0][i]+da[1][u]+f[k].d ==d&&da[0][i]<(d+1)/2&&da[1][u]<(d+1)/2){ sum=sum-(su[0][i]*su[1][u]%MOD)*(su[0][i]*su[1][u]%MOD)%MOD; sum=(sum+MOD)%MOD; } } } cout<<sum; return 0; }