对于每个点都跑最短路, 然后我们得到了个DAG, 在这DAG上更新每条边的答案.

考虑e(u, v)∈DAG对答案的贡献:  假设从S到u得路径数为A[u], 从v出发到达任意点的路径数为B[v], 那么e(u, v)的答案可以加上A[u] * B[v](显然).

A可以按拓扑序递推得到, B可以通过记忆化搜索得到, 都是O(m). 所以总时间复杂度O(nmlogn + nm)

-------------------------------------------------------------------------------------

#include<bits/stdc++.h>
  
#define rep(i, n) for(int i = 0; i < n; i++)
#define clr(x, c) memset(x, c, sizeof(x))
#define REP(x) for(edge* e = head[x]; e; e = e->next)
#define foreach(e, x) for(__typeof(x.begin()); e != x.end(); e++)
#define mod(x) ((x) %= MOD)
 
using namespace std;
 
const int maxn = 1509, maxm = 5009;
const int MOD = 1000000007;
 
struct edge {
int to, w, num;
edge* next;
} E[maxm], *pt = E, *head[maxn];
 
inline void addedge(int u, int v, int d, int _) {
pt->to = v, pt->w = d, pt->num = _;
pt->next = head[u];
head[u] = pt++;
}
 
struct node {
int x, w;
bool operator < (const node &t) const {
return w > t.w;
}
};
 
int d[maxn], cnt[maxn], ans[maxm], A[maxn], B[maxn], n;
 
void dijkstra(int S) {
rep(i, n) d[i] = MOD;
d[S] = 0;
priority_queue<node> Q;
Q.push( (node) {S, 0} );
while(!Q.empty()) {
node t = Q.top(); Q.pop();
if(d[t.x] != t.w) continue;
REP(t.x) if(d[t.x] + e->w < d[e->to]) {
d[e->to] = d[t.x] + e->w;
Q.push( (node) {e->to, d[e->to]} );
}
}
}
 
// get B
int dp(int x) {
if(B[x]) return B[x];
REP(x) if(d[e->to] == d[x] + e->w)
   mod(B[x] += dp(e->to));
return ++B[x];
}
 
//get A
void DFS(int x) {
REP(x) if(d[e->to] == d[x] + e->w) {
mod(A[e->to] += A[x]);
if(!--cnt[e->to]) DFS(e->to);
}
}
 
void dfs(int x) {
REP(x) if(d[e->to] == d[x] + e->w)
if(!cnt[e->to]++) dfs(e->to);
}
 
void work(int x) {
dijkstra(x);
clr(cnt, 0), clr(A, 0), clr(B, 0);
dfs(x), dp(x), A[x] = 1, DFS(x);
rep(i, n)
   REP(i) if(d[i] + e->w == d[e->to])
       mod(ans[e->num] += 1LL * A[i] * B[e->to] % MOD);
}
 
inline int read() {
char c = getchar();
for(; !isdigit(c); c = getchar());
int ans = 0;
for(; isdigit(c); c = getchar())
   ans = ans * 10 + c - '0';
return ans;
}
 
int main() {
freopen("test.in", "r", stdin);
int m;
clr(head, 0), clr(ans, 0);
cin >> n >> m;
rep(i, m) {
int u = read() - 1, v = read() - 1, w = read();
addedge(u, v, w, i);
}
rep(i, n) work(i);
for(int* t = ans; t != ans + m; t++)
   printf("%d\n", *t);
return 0;
}

-------------------------------------------------------------------------------------

2750: [HAOI2012]Road

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 356  Solved: 163
[Submit][Status][Discuss]

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

Source

BZOJ 2750: [HAOI2012]Road( 最短路 )的更多相关文章

  1. bzoj 2750: [HAOI2012]Road

    Description C国有n座城市,城市之间通过m条单向道路连接.一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小.两条最短路不同,当且仅当它们包含的道路序列不同.我 ...

  2. bzoj 2750: [HAOI2012]Road【spfa+dfs】

    枚举起点做spfa,然后一条边在最短路上的条件是dis[e[i].to]==dis[u]+e[i].va,所以每次spfa完之后,dfs出a[i]表示经过i点的最短路的起点数,b[i]表示经过i点的最 ...

  3. BZOJ2750: [HAOI2012]Road

    2750: [HAOI2012]Road Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 261  Solved: 113[Submit][Status ...

  4. [HAOI2012]Road

    2750: [HAOI2012]Road Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 728  Solved: 349[Submit][Status ...

  5. BZOJ 2750 HAOI 2012 Road 高速公路 最短路

    题意: 给出一个有向图,求每条边有多少次作为最短路上的边(任意的起始点). 范围:n <= 1500, m <= 5005 分析: 一个比较容易想到的思路:以每个点作为起点,做一次SPFA ...

  6. BZOJ 2752: [HAOI2012]高速公路(road)( 线段树 )

    对于询问[L, R], 我们直接考虑每个p(L≤p≤R)的贡献,可以得到 然后化简一下得到 这样就可以很方便地用线段树, 维护一个p, p*vp, p*(p+1)*vp就可以了 ----------- ...

  7. BZOJ 3040: 最短路(road) ( 最短路 )

    本来想学一下配对堆的...结果学着学着就偏了... 之前 kpm 写过这道题 , 前面的边不理它都能 AC .. 我也懒得去写前面的加边了... 用 C++ pb_ds 库里的 pairing_hea ...

  8. BZOJ 2752: [HAOI2012]高速公路(road) [线段树 期望]

    2752: [HAOI2012]高速公路(road) Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1219  Solved: 446[Submit] ...

  9. Road(bzoj 2750)

    Description C国有n座城市,城市之间通过m条单向道路连接.一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小.两条最短路不同,当且仅当它们包含的道路序列不同.我 ...

随机推荐

  1. php随笔6-thinkphp OA系统 JS 实时显示当前时间

    不多说,直入主题: JS. // JavaScript Document function showtime() { var today,hour,second,minute,year,month,d ...

  2. PHP学习笔记9-生成图片

    用PHP代码在网页上生成图片 <?php /** * Created by PhpStorm. * User: Administrator * Date: 2015/6/29 * Time: 2 ...

  3. vagrant 入门3

    创建第一个Vagrant虚拟环境以及工程(续集): (8) Provisioning: 通常情况下Box只做最基本的设置,而不是一次到位的设置好所有的环境.Vagrant通常使用chef或者Puppe ...

  4. (C)单链表

    老师版 #include <stdio.h> #include <stdlib.h> // 定于Node数据类型 struct Node { int data; // 数据域 ...

  5. RMAN多种备份脚本分享

    1.相关参数介绍: 命令行参数 描述 TARGET 为目标数据库定义的一个连接字符串,当连接到一个目标数据库时,该连续是SYSDBA连接.该用户拥有启动和关闭数据库的权利,必须属于OSDBA组,必须建 ...

  6. rbd块映射

    rbd块映射: root@u18:~# rbd create kvm/test002.img --size root@u18:~# rbd info kvm/test002.img rbd image ...

  7. Oracle自带的exception

    存储过程中自带的exception: --查询人员资料历史 BEGIN SELECT * INTO Po_Sac01 FROM Sac01 WHERE Aac001 = Pi_Aac001 ); EX ...

  8. web.xml的配置问题

    [转]http://perfy315.iteye.com/blog/2009258 首先 classpath是指 WEB-INF文件夹下的classes目录 ,指的就是java文件编译之后的path. ...

  9. 用二进制方法求两个整数的最大公约数(GCD)

    二进制GCD算法基本原理是: 先用移位的方式对两个数除2,直到两个数不同时为偶数.然后将剩下的偶数(如果有的话)做同样的操作,这样做的原因是如果u和v中u为偶数,v为奇数,则有gcd(u,v)=gcd ...

  10. 2014年百度之星程序设计大赛 资格赛第一题 (longlong)

    解题思路: 只要看(A-V)*K 这个公式的更新值是否大于等于A ,大于的话继续循环,否则报错 注意一点,数据会爆int WA代码: #include<stdio.h> int main( ...