zoukankan      html  css  js  c++  java
  • 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
    ", 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 }

     

  • 相关阅读:
    基础【五】字典的操作方法
    基础【四】列表的操作方法
    基础【三】字符串的操作方法
    基础【二】while循环及基本运算符
    基础【一】基础数据类型
    C++ string 深拷贝 与 浅拷贝
    多进程引用的动态链接库中的全局变量问题
    C++ 在类里面使用多线程技术
    openwrt 解决包依赖关系
    lua 的元表与元方法
  • 原文地址:https://www.cnblogs.com/HarryHuang2004/p/13121293.html
Copyright © 2011-2022 走看看