概述
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
题解:
把每个点当作起点做spfa。
每次都处理两个数组a[i],b[i]分别表示从起点到点i的最短路数,和从i出发的最短路数。
然后枚举每条边,如果这条边在当前最短路图中。设这条边从i指向j,那就把a[i]*b[j]累加入这条边的答案。
对于这两个数组。我们可以在最短路图上dp一下,或者叫它dfs。
首先b数组比较好做。直接用它的后继结点更新即可.
对于a数组.我们需要先处理一个pre数组.pre[i]表示在最短路图中有多少条边指向i。
然后在做a数组的过程中.我们显然要正着算。
对于一个点,只有它被所有指向它的边的起点更新过之后,再去用这个点更新其他点。
代码:
#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】所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复