【BZOJ】【2750】【HAOI2012】Road

最短路+拓扑序DP


  orz zyf & lyd

  统计每条边在多少条最短路径上……其实可以统计 有多少条最短路径经过了x,以及y出发到达任意一个结束点有多少种走法(沿最短路)

  我们可以用Dijkstra求出以 i 为起点的最短路径图,它是一个DAG,然后我们用dij扩展的顺序(一个拓扑序)来搞DP!

    令a[x]表示从 i 沿最短路走到 x 的方案数,b[x]表示从 x 往出走,沿最短路走到任意一个结束结点的总方案(就是经过x的最短路条数?只不过只看后半段)

  其实就是将最短路分开两半进行统计了……然后乘一下……

  通过这题的思路可以搞CTSC2015 Day1 T1?

  跪了,pq应该把<定义为a.d>b.d……唉真是傻逼了

 1 /**************************************************************
 2     Problem: 2750
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:2276 ms
 7     Memory:1388 kb
 8 ****************************************************************/
 9  
10 //BZOJ 2750
11 #include<queue>
12 #include<vector>
13 #include<cstdio>
14 #include<cstring>
15 #include<cstdlib>
16 #include<iostream>
17 #include<algorithm>
18 #define rep(i,n) for(int i=0;i<n;++i)
19 #define F(i,j,n) for(int i=j;i<=n;++i)
20 #define D(i,j,n) for(int i=j;i>=n;--i)
21 #define pb push_back
22 using namespace std;
23 inline int getint(){
24     int v=0,sign=1; char ch=getchar();
25     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
26     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
27     return v*sign;
28 }
29 const int N=1510,M=5010,INF=~0u>>2;
30 const int P=1000000007;
31 typedef long long LL;
32 /******************tamplate*********************/
33 int to[M],next[M],len[M],head[N],cnt;
34 void add(int x,int y,int z){
35     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt; len[cnt]=z;
36 }
37 struct node{
38     int x,d;
39     bool operator < (const node &b)const{ return d>b.d;}
40 };
41 int n,m,v[N],a[N],b[N],c[N],d[N];
42 priority_queue<node>Q;
43 int ans[M];
44 void dijkstra(int S){
45     memset(d,0x3f,sizeof d);
46     memset(v,0,sizeof v);
47     d[S]=0;
48     int t=0;
49     Q.push((node){S,0});
50     while(!Q.empty()){
51         int x=Q.top().x; Q.pop();
52         if (v[x]) continue;
53         v[x]=++t;
54         for(int i=head[x];i;i=next[i]){
55             int y=to[i],l=len[i];
56             if (d[y]>d[x]+l){
57                 d[y]=d[x]+l;
58                 Q.push((node){y,d[y]});
59             }
60         }
61     }
62     F(i,1,n) if (v[i]) c[v[i]]=i;
63     memset(a,0,sizeof a); a[c[1]]=1;
64     F(i,1,n) b[i]=1;
65     F(x,1,t)
66         for(int i=head[c[x]];i;i=next[i])
67             if (d[to[i]]==d[c[x]]+len[i]) 
68                 a[to[i]]=(a[to[i]]+a[c[x]])%P;
69     D(x,t,1)
70         for(int i=head[c[x]];i;i=next[i])
71             if (d[to[i]]==d[c[x]]+len[i]) 
72                 b[c[x]]=(b[c[x]]+b[to[i]])%P;
73     F(x,1,n)
74         for(int i=head[x];i;i=next[i])
75             if (d[to[i]]==d[x]+len[i])
76                 ans[i]=(ans[i]+(LL)a[x]*b[to[i]]%P)%P;
77 }
78 int main(){
79 #ifndef ONLINE_JUDGE
80     freopen("2750.in","r",stdin);
81     freopen("2750.out","w",stdout);
82 #endif
83     n=getint(); m=getint();
84     F(i,1,m){
85         int x=getint(),y=getint(),z=getint();
86         add(x,y,z);
87     }
88     F(i,1,n) dijkstra(i);
89     F(i,1,m) printf("%d\n",ans[i]);
90     return 0;
91 }
View Code

2750: [HAOI2012]Road

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 347  Solved: 155
[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

[Submit][Status][Discuss]
posted @ 2015-05-05 22:38  Tunix  阅读(274)  评论(0编辑  收藏  举报