我是靠谱客的博主 暴躁康乃馨,这篇文章主要介绍【bzoj2750】【HAOI2012】【Road】【最短路+dp】,现在分享给大家,希望可以做个参考。

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

Sample Output

2
3
2
1

HINT

数据规模

30%的数据满足:n≤15、m≤30

60%的数据满足:n≤300、m≤1000

100%的数据满足:n≤1500、m≤5000、w≤10000

题解:

把每个点当作起点做spfa。

每次都处理两个数组a[i],b[i]分别表示从起点到点i的最短路数,和从i出发的最短路数。

然后枚举每条边,如果这条边在当前最短路图中。设这条边从i指向j,那就把a[i]*b[j]累加入这条边的答案。

对于这两个数组。我们可以在最短路图上dp一下,或者叫它dfs。

首先b数组比较好做。直接用它的后继结点更新即可.

对于a数组.我们需要先处理一个pre数组.pre[i]表示在最短路图中有多少条边指向i。

然后在做a数组的过程中.我们显然要正着算。

对于一个点,只有它被所有指向它的边的起点更新过之后,再去用这个点更新其他点。

代码:

复制代码
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
#include<iostream> #include<cstdio> #include<cstring> #define P 1000000007 #define N 2000 #define M 5010 using namespace std; struct use{int st,en,v;}e[M]; int point[N],next[M],x,y,v,n,m,cnt,p[N],dis[N],l[N*100]; long long ans[M],a[N],b[N]; bool f[N]; void add(int x,int y,int v){ next[++cnt]=point[x];point[x]=cnt; e[cnt].st=x;e[cnt].en=y;e[cnt].v=v; } int spfa(int x){ int h(0),t(1),u; memset(dis,127/3,sizeof(dis));memset(f,false,sizeof(f)); dis[x]=0;l[t]=x;f[x]=true; while (h<t){ u=l[++h];f[u]=false; for (int i=point[u];i;i=next[i]) if (dis[e[i].en]>dis[u]+e[i].v){ dis[e[i].en]=dis[u]+e[i].v; if (!f[e[i].en]){f[e[i].en]=true;l[++t]=e[i].en; } } } } void dfs1(int x){ f[x]=true; for (int i=point[x];i;i=next[i]){ if (dis[e[i].en]==dis[x]+e[i].v){ p[e[i].en]++;if (!f[e[i].en]) dfs1(e[i].en); } } } void dfs2(int x){ for (int i=point[x];i;i=next[i]){ if (dis[e[i].en]==dis[x]+e[i].v){ p[e[i].en]--;(a[e[i].en]+=a[x])%=P;if (!p[e[i].en]) dfs2(e[i].en); } } } void dfs3(int x){ b[x]=1; for (int i=point[x];i;i=next[i]){ if (dis[e[i].en]==dis[x]+e[i].v){ if (!b[e[i].en]) dfs3(e[i].en);(b[x]+=b[e[i].en])%=P; } } } int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&v);add(x,y,v);} for (int i=1;i<=n;i++){ spfa(i);memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(f,0,sizeof(f)); dfs1(i);a[i]=1;dfs2(i);dfs3(i); for (int j=1;j<=m;j++){ if (dis[e[j].en]==dis[e[j].st]+e[j].v) (ans[j]+=a[e[j].st]*b[e[j].en])%=P; } } for (int i=1;i<=m;i++){printf("%lldn",ans[i]);} }



最后

以上就是暴躁康乃馨最近收集整理的关于【bzoj2750】【HAOI2012】【Road】【最短路+dp】的全部内容,更多相关【bzoj2750】【HAOI2012】【Road】【最短路+dp】内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部