BZOJ 4055 Misc
比较复杂的一道DP。
设两点(i,j)之间最短路为dis[i][j],则
可转化为:
将该式前后分立,可得:
其中,可以单独求出,后面的部分则需要DP。
设为b(x),枚举i,并计算出从i出发的每个点的dis。
对于每个到达的点k,b(k)可从k相邻的点的b得出。
显然,在枚举过程中可以更新一波答案:
当然,别忘了更新b值:
代码:
1 #include <bits/stdc++.h>
2 #define sir(i, p) for(sides *i = star[p]; i; i = i -> aftr)
3 using namespace std;
4 const int N = 1e3 + 5;
5 int n, m, l, r, a[N], q[N], dis[N], ind[N];
6 double pout[N];
7 long double bck[N], rnt[N];
8 priority_queue <pair <int, int> > queues;
9 bool vis[N];
10 struct sides {
11 int vv, sis;
12 sides *aftr;
13 long double ends;
14 }*star[N], lenss[N << 3];
15 inline void moree (int x, int y, int z, double w) ;
16 void pushups (int x) ;
17 void solve (int x) {
18 dis[x] = 0;
19 queues.push (make_pair (0, x));
20 while (!queues.empty()) {
21 int u = queues.top().second;
22 queues.pop();
23 if (vis[u])
24 continue;
25 vis[u] = 1;
26 sir (i, u)
27 if (dis[i -> vv] > dis[u] + i -> sis) {
28 dis[i -> vv] = dis[u] + i -> sis;
29 queues.push (make_pair (-dis[i -> vv], i -> vv));
30 }
31 }
32 return ;
33 }
34 void doit (int x) {
35 for (int p = r; p > 1; p --) {
36 int u = q[p];
37 sir (i, u)
38 if(dis[i->vv] == dis[u]+i->sis) {
39 int v = i->vv; bck[u] += i->ends*bck[v];
40 }
41 pout[u] += a[x]*rnt[u]*bck[u];
42 bck[u] += (long double)a[u]/rnt[u];
43 }
44 return ;
45 }
46 int main() {
47 scanf ("%d%d", &n, &m);
48 for (int i = 1; i <= n; i ++)
49 scanf("%d", &a[i]);
50 for (int i = 1; i <= m; i ++) {
51 int x, y, z;
52 double w;
53 scanf("%d%d%d%lf", &x, &y, &z, &w);
54 moree(x, y, z, w);
55 }
56 for (int i = 1; i <= n; i ++) {
57 memset (rnt, 0, sizeof rnt);
58 memset (bck, 0, sizeof bck);
59 memset (vis, 0, sizeof vis);
60 memset (dis, 0x3f, sizeof dis);
61 solve (i);
62 pushups (i);
63 doit (i);
64 }
65 for (int i = 1; i <= n; i ++)
66 printf ("%.10f\n", pout[i]);
67 return 0;
68 }
69 inline void moree (int x, int y, int z, double w) {
70 static int _; sides* ls;
71 ls = &lenss[++_];
72 ls -> vv = y;
73 ls -> sis = z;
74 ls -> ends = w;
75 ls -> aftr = star[x];
76 star[x] = ls;
77 ls = &lenss[++_];
78 ls -> vv = x;
79 ls -> sis = z;
80 ls -> ends = w;
81 ls -> aftr = star[y];
82 star[y] = ls;
83 return ;
84 }
85 void pushups (int x) {
86 q[r = 1] = x;
87 l = 0;
88 rnt[x] = 1;
89 for (int i = 1; i <= n; i ++)
90 sir (j, i) {
91 if (dis[i] + j -> sis == dis[j -> vv])
92 ind[j -> vv] ++;
93 }
94 while (r > l) {
95 int u = q[++ l];
96 sir(i, u)
97 if (dis[u] + i -> sis == dis[i -> vv]) {
98 if (!-- ind[i -> vv])
99 q[++r] = i -> vv;
100 rnt[i -> vv] += rnt[u] * i -> ends;
101 }
102 }
103 return ;
104 }