[HAOI2012]道路
题目描述
C国有n座城市,城市之间通过m条[b]单向[/b]道路连接。一条路径被称为最短路,当且仅当不存在从 它的起点到终点的另外一条路径总长度比它小。两条最短路不同,当且仅当它们包含的道路序列不同。我们需要对每条道路的重要性进行评估,评估方式为计算有多 少条不同的最短路经过该道路。现在,这个任务交给了你。
输入输出格式
输入格式:第一行包含两个正整数n、m
接下来m行每行包含三个正整数u、v、w,表示有一条从u到v长度为w的道路
输出格式:输出应有m行,第i行包含一个数,代表经过第i条道路的最短路的数目对[b]1000000007取模[/b]后的结果
输入输出样例
说明
数据规模
30%的数据满足:n≤15、m≤30
60%的数据满足:n≤300、m≤1000
100%的数据满足:n≤1500、m≤5000、w≤10000
以每一个点为起点,做一次SPFA,把在最短路上的边标记
设S到i的路径数cnt1[i],在设i到其他点的最短路数cnt2[i]
因为选出来的边构成的图无环,所以用拓扑排序来递推
cnt1[v]+=cnt1[u]
至于cnt2数组,用逆拓扑序递推
于是一条边(u,v)的ans+=cnt1[u]*cnt2[v]
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 struct Node 8 { 9 int next,to,dis; 10 }edge[20001]; 11 int num,head[10001],d[10001]; 12 long long cnt1[10001],cnt2[10001],ans[20001],n,m; 13 int q[1000001]; 14 bool vis[10001],pd[10001]; 15 long long dist[10001]; 16 int Mod=1000000007; 17 void add(int u,int v,int d) 18 { 19 num++; 20 edge[num].next=head[u]; 21 head[u]=num; 22 edge[num].to=v; 23 edge[num].dis=d; 24 } 25 void SPFA(int S) 26 {queue<int>Q; 27 int i,j; 28 memset(pd,0,sizeof(pd)); 29 memset(vis,0,sizeof(vis)); 30 memset(dist,127/3,sizeof(dist)); 31 memset(d,0,sizeof(d)); 32 Q.push(S); 33 dist[S]=0; 34 while (Q.empty()==0) 35 { 36 int u=Q.front(); 37 Q.pop(); 38 vis[u]=0; 39 for (i=head[u];i;i=edge[i].next) 40 { 41 int v=edge[i].to; 42 if (dist[v]>dist[u]+edge[i].dis) 43 { 44 dist[v]=dist[u]+edge[i].dis; 45 if (vis[v]==0) 46 { 47 vis[v]=1; 48 Q.push(v); 49 } 50 } 51 } 52 } 53 for (i=1;i<=n;i++) 54 for (j=head[i];j;j=edge[j].next) 55 if (dist[i]+edge[j].dis==dist[edge[j].to]) 56 pd[j]=1,d[edge[j].to]++; 57 } 58 void Top_sort(int S) 59 {int i,j; 60 memset(cnt1,0,sizeof(cnt1)); 61 memset(cnt2,0,sizeof(cnt2)); 62 int h=0,t=1; 63 q[1]=S; 64 cnt1[S]=1; 65 while (h<t) 66 { 67 h++; 68 int u=q[h]; 69 for (i=head[u];i;i=edge[i].next) 70 { 71 int v=edge[i].to; 72 if (pd[i]) 73 { 74 d[v]--; 75 cnt1[v]+=cnt1[u]; 76 cnt1[v]%=Mod; 77 if (d[v]==0) 78 { 79 t++; 80 q[t]=v; 81 } 82 } 83 } 84 } 85 for (i=t;i>=1;i--) 86 { 87 int u=q[i]; 88 cnt2[u]++; 89 for (j=head[u];j;j=edge[j].next) 90 if (pd[j]) 91 { 92 int v=edge[j].to; 93 cnt2[u]+=cnt2[v]; 94 cnt2[u]%=Mod; 95 } 96 } 97 for (i=1;i<=n;i++) 98 for (j=head[i];j;j=edge[j].next) 99 if (pd[j]) 100 { 101 int v=edge[j].to; 102 ans[j]+=cnt1[i]*cnt2[v]; 103 ans[j]%=Mod; 104 } 105 } 106 int main() 107 {int i,u,v,d; 108 cin>>n>>m; 109 for (i=1;i<=m;i++) 110 { 111 scanf("%d%d%d",&u,&v,&d); 112 add(u,v,d); 113 } 114 for (i=1;i<=n;i++) 115 { 116 SPFA(i); 117 Top_sort(i); 118 } 119 for (i=1;i<=m;i++) 120 printf("%lld\n",ans[i]); 121 }