这题不开O2怎么过=。=
可能这种有关最短路的计数题做多了就有些感觉了......
以每个点为基准跑出一张最短路图,然后对每个边$(u,v)$统计两个东西。一个$pre[u]$表示到达$u$这个起点的路径条数,一个$nxt[v]$表示从$v$开始的最短路数,然后对每条边来一下乘法原理。
然后是这两个玩意的统计方法,$pre[]$可以在最短路图上跑拓扑排序得出,$nxt[]$可以跑记忆化搜索,这样统计的复杂度是$O(n+m)$的,总复杂度大概$O(nmlog$ $n)$?然而并不能卡过去......
1 // luogu-judger-enable-o2 2 #include<queue> 3 #include<cstdio> 4 #include<cctype> 5 #include<cstring> 6 #include<algorithm> 7 using namespace std; 8 const int N=1505,M=5005; 9 const long long mod=1e9+7; 10 struct a{int node,dist;}; 11 bool operator < (a x,a y) 12 { 13 return x.dist>y.dist; 14 } 15 priority_queue<a> hp; 16 int dis[N],vis[N],pre[N],nxt[N],deg[N],ans[M],que[N]; 17 int p[N],noww[M],from[M],goal[M],val[M]; 18 int n,m,t1,t2,t3,cnt,f,b; 19 inline int read() 20 { 21 int ret=0; 22 char ch=getchar(); 23 while(!isdigit(ch)) 24 ch=getchar(); 25 while(isdigit(ch)) 26 ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar(); 27 return ret; 28 } 29 void link(int f,int t,int v) 30 { 31 noww[++cnt]=p[f],p[f]=cnt; 32 goal[cnt]=t,val[cnt]=v,from[cnt]=f; 33 } 34 void Dijkstra(int s) 35 { 36 register int i; 37 memset(vis,0,sizeof vis); 38 memset(dis,0x3f,sizeof dis); 39 dis[s]=0,hp.push((a){s,0}); 40 while(!hp.empty()) 41 { 42 a tt=hp.top(); hp.pop(); int tn=tt.node; 43 if(vis[tn]) continue ; vis[tn]=true; 44 for(i=p[tn];i;i=noww[i]) 45 if(dis[goal[i]]>dis[tn]+val[i]) 46 { 47 dis[goal[i]]=dis[tn]+val[i]; 48 hp.push((a){goal[i],dis[goal[i]]}); 49 } 50 } 51 } 52 void getpre(int nde) 53 { 54 register int i,j; 55 for(i=1;i<=n;i++) 56 for(j=p[i];j;j=noww[j]) 57 if(dis[goal[j]]==dis[i]+val[j]) deg[goal[j]]++; 58 que[f=b=0]=nde,pre[nde]=1; 59 while(f<=b) 60 { 61 int tn=que[f++]; 62 for(i=p[tn];i;i=noww[i]) 63 if(dis[goal[i]]==dis[tn]+val[i]) 64 { 65 pre[goal[i]]+=pre[tn]; 66 if(!(--deg[goal[i]])) que[++b]=goal[i]; 67 } 68 } 69 } 70 void getnxt(int nde) 71 { 72 nxt[nde]=1; 73 for(int i=p[nde];i;i=noww[i]) 74 if(dis[goal[i]]==dis[nde]+val[i]) 75 { 76 if(!nxt[goal[i]]) getnxt(goal[i]); 77 nxt[nde]+=nxt[goal[i]]; 78 } 79 } 80 int main () 81 { 82 register int i,j; 83 scanf("%d%d",&n,&m); 84 for(int i=1;i<=m;i++) 85 scanf("%d%d%d",&t1,&t2,&t3),link(t1,t2,t3); 86 for(i=1;i<=n;i++) 87 { 88 Dijkstra(i); 89 memset(pre,0,sizeof pre); 90 memset(nxt,0,sizeof nxt); 91 memset(deg,0,sizeof deg); 92 getpre(i),getnxt(i); 93 for(j=1;j<=m;j++) 94 if(dis[from[j]]+val[j]==dis[goal[j]]) 95 ans[j]+=1ll*pre[from[j]]*nxt[goal[j]]%mod,ans[j]%=mod; 96 } 97 for(i=1;i<=m;i++) 98 printf("%d\n",ans[i]); 99 return 0; 100 }
原文地址:https://www.cnblogs.com/ydnhaha/p/9795062.html
时间: 2024-10-10 18:28:55