【bzoj2750】【HAOI2012】【Road】【最短路+dp】
来源:互联网 发布:淘宝赚钱助手是真的吗 编辑:程序博客网 时间:2024/06/15 20:31
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 5010using 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("%lld\n",ans[i]);}}
0 0
- 【bzoj2750】【HAOI2012】【Road】【最短路+dp】
- BZOJ2750[HAOI2012]Road 最短路
- BZOJ2750 [HAOI2012]Road(最短路)
- bzoj 2750: [HAOI2012]Road 最短路+dp
- [bzoj2750][HAOI2012]Road
- bzoj2750 Road 最短路&记忆化搜索
- [BZOJ2750][HAOI2012]Road(SPFA+拓扑排序)
- 3040: 最短路(road)
- 3040: 最短路(road)
- 【bzoj3040】最短路(road)
- bzoj3040: 最短路(road)
- 【bzoj3040】最短路(road)
- Reverse a Road 最短路
- 【BZOJ 3040】 最短路(road)
- BZOJ3040最短路(road)
- 2750: [HAOI2012]Road
- 【bzoj 2750】: [HAOI2012]Road
- BZOJ2752 [HAOI2012]高速公路(road)
- 【NDK开发】JNI与NDK关系
- Android Adapter以及getView()方法的理解
- 剑指offer:孩子们的游戏(圆圈中最后剩下的数)
- 10.6上课——problem1切割木板(USACO 2006 November Gold)
- HDU 4622 Reincarnation
- 【bzoj2750】【HAOI2012】【Road】【最短路+dp】
- FZU 1759 Super A^B mod C(数论+快速幂+欧拉函数)
- IOS 开发笔记——如何用 collection 创建瀑布流
- ES6详解六:赋值语法糖 destructing & spread
- 关于fragment、ActionBar与ViewPager的一些总结
- NUKE推荐的cybersecurityventures
- Crush The Crash--汇编级看函数调用
- iOS--textField
- 将字符串写入 data/data/包名/files