ZOJ Monthly, October 2010
好不容易看到一道图论,可惜没搞定。。
点数很多,N = 10000,很明显不能暴搜,单源最短路径,dijkstra我都没敢写,O(n^2),怕超时,记得有个O(nlog(n))的heap优化,还没学会,赛后看了解题报告,就是个最短路问题,只不过加了个DP过程,设s[v]表示源点到点v的路径数,t[v]表示点v到其余各点的路径数,则经过点v的最短路径总数就可以表示成s[v] * t[v],s[v]和t[v]都可以用DP的思想求的,s[v]要按照拓扑序DP,t[v]则按照反拓扑序DP。
我的SPFA写比较烂,跑了1000多ms。。
我发现C++里有个fill(a, a + n, key)函数,可以把a数组赋值为key,挺好用的。。。
代码
1 #include<iostream>
2 #include<cstdio>
3 #include<string.h>
4 #include<stdlib.h>
5 #include<algorithm>
6 #define MM 50004
7 #define NN 10004
8 #define LL long long
9 #define INF 0x3fffffff
10 #define MOD 10000000000LL
11
12 using namespace std;
13 typedef struct node{
14 int v, wt;
15 struct node *nxt;
16 }NODE;
17
18 NODE edg[MM];
19 NODE *Link[NN];
20 int idx;
21 int N, M, Q;
22 int stack[NN];
23 int mark[NN];
24 int dis[NN];
25 int ord[NN];
26 LL s[NN];
27 LL t[NN];
28
29 int cmp(const void *a, const void *b){
30 return dis[*(int *)a] - dis[*(int *)b];
31 }
32
33 void Add(int u, int v, int wt){
34 idx++;
35 edg[idx].v = v;
36 edg[idx].wt = wt;
37 edg[idx].nxt = Link[u];
38 Link[u] = edg + idx;
39 }
40
41 void Spfa(){
42 int i, top, u, v, wt;
43 top = 0;
44 for (i = 0; i < N; i++){
45 stack[++top] = i;
46 mark[i] = 1;
47 dis[i] = INF;
48 }
49 dis[0] = 0;
50 while(top){
51 u = stack[top--];
52 mark[u] = 0;
53 for (NODE *p = Link[u]; p; p = p->nxt){
54 v = p->v;
55 wt = p->wt;
56 if (dis[v] > dis[u] + wt){
57 dis[v] = dis[u] + wt;
58 if (!mark[v]){
59 mark[v] = 1;
60 stack[++top] = v;
61 }
62 }
63 }
64 }
65 }
66
67 LL mul(LL lhs, LL rhs){//布斯乘法
68 LL sq = 100000;
69 LL lhs1 = lhs % sq;
70 LL rhs1 = rhs % sq;
71
72 return ((lhs / sq * rhs1 + rhs / sq * lhs1) * sq + lhs1 * rhs1) % MOD;
73 }
74
75 void Solve(){
76 Spfa();
77 int i, u;
78 for(i = 0; i < N; i++){
79 ord[i] = i;
80 }
81 qsort(ord, N, sizeof(int), cmp);
82 fill(s, s + N, 0);
83 s[0] = 1;
84 for (u = 0; u < N; u++){
85 for (NODE *p = Link[ord[u]]; p; p = p->nxt){
86 if(dis[p->v] == dis[ord[u]] + p->wt){
87 s[p->v] = (s[p->v] + s[ord[u]]) % MOD;
88 }
89 }
90 }
91 fill(t, t + N, 1);
92 for (u = N - 1; u >= 0; u--){
93 for (NODE *p = Link[ord[u]]; p; p = p->nxt){
94 if(dis[p->v] == dis[ord[u]] + p->wt){
95 t[ord[u]] = (t[ord[u]] + t[p->v]) % MOD;
96 }
97 }
98 }
99 int a;
100 while(Q--){
101 scanf("%d", &a);
102 printf("%010lld\n", mul(s[a], t[a]));
103 }
104 }
105 int main()
106 {
107 int a, b, d;
108 while(scanf("%d%d%d", &N, &M, &Q) != EOF){
109 idx = 0; memset(Link, 0, sizeof(Link));
110 while(M--){
111 scanf("%d%d%d", &a, &b, &d);
112 Add(a, b, d);
113 }
114 Solve();
115 }
116 return 0;
117 }
118