给定一个无向图,一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小。两条最短路不同,当且仅当它们包含的道路序列不同。我们需要对每条道路的重要性进行评估,评估方式为计算有多少条不同的最短路经过该道路。(nleq 1500,mleq 5000,wleq 10000)
Solution
枚举每个点作为起点,跑出最短路径图,对其拓扑排序后,DP 统计出每个点发出和从起点到达该点的最短路的总数,然后扫一遍所有边统计答案即可。
注意可能有重边
#include <bits/stdc++.h>
using namespace std;
#define reset(x) memset(x,0,sizeof x)
#define reset3f(x) memset(x,0x3f,sizeof x)
#define int long long
const int mod = 1000000007;
namespace topo {
const int N=10005;
vector<int> g[N];
int n,f[N],h[N],a[N],b[N],c[N],ans[N],vis[N],ind,cnt,s[N];
void make(int t1,int t2,int t3) {
g[t1].push_back(t2);
a[++ind]=t1; b[ind]=t2; c[ind]=t3;
}
void dfs(int p) {
vis[p]=1;
for(int q:g[p]) {
if(vis[q]==0) dfs(q);
}
s[++cnt]=p;
}
void solve(int v0) {
memset(f,0,sizeof f);
memset(h,0,sizeof h);
memset(vis,0,sizeof vis);
memset(s,0,sizeof s);
cnt=0;
f[v0]=1;
dfs(v0);
for(int i=cnt;i>=1;i--) {
int p=s[i];
for(int q:g[p]) f[q]+=f[p], f[q]%=mod;
}
for(int i=1;i<=cnt;i++) {
int p=s[i]; h[p]++;
for(int q:g[p]) h[p]+=h[q], h[p]%=mod;
}
for(int i=1;i<=ind;i++) {
ans[c[i]]+=f[a[i]]*h[b[i]]%mod;
ans[c[i]]%=mod;
}
memset(a,0,sizeof a);
memset(b,0,sizeof b);
memset(c,0,sizeof c);
for(int i=1;i<=n;i++) g[i].clear();
ind=0;
}
}
int ax[10005],bx[10005],cx[10005];
int n,m,t1,t2,t3;
namespace sp {
const int N=10005;
vector<pair<int,int> > g[N];
int n,v0=1,d[N];
void make(int t1,int t2,int t3) {
g[t1].push_back(make_pair(t2,t3));
}
void reset_graph() {
for(int i=0;i<=n;i++) g[i].clear();
}
void solve() {
priority_queue<pair<int,int> > qu;
reset3f(d);
d[v0]=0;
qu.push(make_pair(0,v0));
while(qu.size()) {
int p=qu.top().second,r=qu.top().first;
qu.pop();
if(r+d[p]) continue;
for(int i=0;i<g[p].size();i++) {
int q=g[p][i].first,w=g[p][i].second;
if(d[q]>d[p]+w) {
d[q]=d[p]+w;
qu.push(make_pair(-d[q],q));
}
}
}
for(int i=1;i<=m;i++) {
if(d[ax[i]]+cx[i]==d[bx[i]]) topo::make(ax[i],bx[i],i);
}
}
}
signed main() {
ios::sync_with_stdio(false);
cin>>n>>m;
sp::n=topo::n=n;
for(int i=1;i<=m;i++) {
cin>>t1>>t2>>t3;
sp::g[t1].push_back(make_pair(t2,t3));
ax[i]=t1; bx[i]=t2; cx[i]=t3;
}
for(int i=1;i<=n;i++) {
sp::v0=i;
sp::solve();
topo::solve(i);
}
for(int i=1;i<=m;i++) cout<<topo::ans[i]<<endl;
}