bzoj 2750: [HAOI2012]Road
Description
C国有n座城市,城市之间通过m条单向道路连接。一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小。两条最短路不同,当且仅当它们包含的道路序列不同。我们需要对每条道路的重要性进行评估,评估方式为计算有多少条不同的最短路经过该道路。现在,这个任务交给了你。
Input
第一行包含两个正整数n、m
接下来m行每行包含三个正整数u、v、w,表示有一条从u到v长度为w的道路
Output
输出应有m行,第i行包含一个数,代表经过第i条道路的最短路的数目对1000000007取模后的结果
Sample Input
4 4
1 2 5
2 3 5
3 4 5
1 4 8
1 2 5
2 3 5
3 4 5
1 4 8
Sample Output
2
3
2
1
3
2
1
HINT
数据规模
30%的数据满足:n≤15、m≤30
60%的数据满足:n≤300、m≤1000
100%的数据满足:n≤1500、m≤5000、w≤10000
Source
社交网络的加强版。floyd肯定是跑不过了。
首先枚举一个起点开始跑spfa,然后在最短路图上统计答案,(最短路图是DAG)
对于一条在最短路图上的边(x.y),被经过次数是(源点到x的方案数)*(y的后继结点个数)。。。
这个很显然,然后因为是DAG这两个值可以通过拓扑排序或记忆化搜索来解决。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | // MADE BY QT666 #include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #include<cstring> #include<vector> #include<queue> using namespace std; typedef long long ll; const int N=100050; const int Mod=1000000007; int head[N],to[N],nxt[N],v[N],cnt,n,m; ll ans[N],dp[N],dp2[N],dis[N],vis[N],du[N]; struct data{ int x,y,w; }e[N]; struct Data{ int x,w; }; vector<Data> p[N]; void lnk( int x, int y, int z){ to[++cnt]=y,nxt[cnt]=head[x],v[cnt]=z,head[x]=cnt; p[y].push_back((Data){x,z}); } queue< int > Q; void spfa( int s){ for ( int i=1;i<=n;i++) dis[i]=19260817,vis[i]=0; Q.push(s);vis[s]=1;dis[s]=0; while (!Q.empty()){ int x=Q.front();Q.pop();vis[x]=0; for ( int i=head[x];i;i=nxt[i]){ int y=to[i]; if (dis[y]>dis[x]+v[i]){ dis[y]=dis[x]+v[i]; if (!vis[y]) Q.push(y),vis[y]=1; } } } } int dfs1( int x){ if (dp[x]) return dp[x]; for ( int i=0;i<p[x].size();i++){ int y=p[x][i].x; if (dis[y]==dis[x]-p[x][i].w){du[y]++;(dp[x]+=dfs1(y))%=Mod;} } return dp[x]; } void topsort(){ for ( int i=1;i<=n;i++) if (du[i]==0) Q.push(i); while (!Q.empty()){ int x=Q.front();Q.pop(); for ( int i=0;i<p[x].size();i++){ int y=p[x][i].x; if (dis[y]==dis[x]-p[x][i].w){ du[y]--;dp2[y]+=dp2[x]; if (du[y]==0) Q.push(y); } } } } int main(){ freopen( "roadsw.in" , "r" ,stdin); freopen( "roadsw.out" , "w" ,stdout); scanf( "%d%d" ,&n,&m); for ( int i=1;i<=m;i++){ scanf( "%d%d%d" ,&e[i].x,&e[i].y,&e[i].w); lnk(e[i].x,e[i].y,e[i].w); } for ( int i=1;i<=n;i++){ for ( int j=1;j<=n;j++) dp[j]=dp2[j]=0,du[j]=0; spfa(i); dp[i]=1; for ( int j=1;j<=n;j++) dp[j]=dfs1(j); for ( int j=1;j<=n;j++) dp2[j]=1;topsort(); for ( int j=1;j<=m;j++) if (dis[e[j].x]+e[j].w==dis[e[j].y]) (ans[j]+=dp[e[j].x]*dp2[e[j].y])%=Mod; } for ( int i=1;i<=m;i++) printf( "%lld\n" ,ans[i]); return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步