[XSY 1539] 狂飙突进的幻想乡

题意

  给定一张 $n$ 个点 $m$ 条边的无向图.

  每条边有两个信息 $x, y$ , 这条边的边权是 $ax + (1 - a)y$ .

  给定源点 $S$ 和汇点 $T$ , 求当 $a \in [0, 1]$ 时, $E(minpath(S, T))$ .

  $n \le 200, m \le 400$ .

分析1  蒙特卡洛算法 + SPFA

  不论是期望还是概率, 都是在某种量化意义下, 将试验次数取无穷大.

  我们均匀取点, 进行 SPFA , 然后取平均值.

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cctype>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <vector>
 8 using namespace std;
 9 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
10 #define fore(it, x) for (register vector<Edge>::iterator it = g[x].begin(); it != g[x].end(); it++)
11 #define db double
12 inline int rd(void) {
13     int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1;
14     int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f;
15 }
16
17 const db EPS = 1e-7;
18 inline int sign(db x) { return fabs(x) < EPS ? 0 : x < 0 ? -1 : 1; }
19 inline int cmp(db x, db y) { return sign(x - y); }
20
21 const int N = 205;
22 const db INF = 1e20;
23
24 int n, m, S, T;
25 struct Edge {
26     int v; db x, y;
27     inline db d(db a) { return a * x + (1 - a) * y; }
28 };
29 vector<Edge> g[N];
30
31 inline void Init(int s, int t, db x, db y) {
32     g[s].push_back((Edge){t, x, y});
33     g[t].push_back((Edge){s, x, y});
34 }
35
36 int nT; db res;
37 int q[N], qh, qt; bool inq[N]; db dis[N];
38
39 db SPFA(db a) {
40     memset(q, 0, sizeof q), qh = qt = 0, memset(inq, false, sizeof inq), fill(dis + 1, dis + n + 1, INF);
41     q[++qt] = S, inq[S] = true, dis[S] = 0;
42     while (qh != qt) {
43         int x = q[qh = qh % n + 1];
44         fore(it, x)
45             if (cmp(dis[x] + it->d(a), dis[it->v]) < 0) {
46                 dis[it->v] = dis[x] + it->d(a);
47                 if (!inq[it->v])
48                     q[qt = qt % n + 1] = it->v, inq[it->v] = true;
49             }
50         inq[x] = false;
51     }
52     return dis[T];
53 }
54
55 int main(void) {
56     #ifndef ONLINE_JUDGE
57         //  freopen("C.in", "r", stdin);
58     #endif
59
60     srand(time(0));
61
62     n = rd(), m = rd(), S = rd(), T = rd();
63     F(i, 1, m) {
64         int s = rd(), t = rd();
65         db x, y; scanf("%lf %lf", &x, &y);
66         Init(s, t, x, y);
67     }
68
69     nT = 100000000 / (5 * n);
70     db V = 1.0 / (nT-1), a = 0; // seperated equally
71     for (int t = 1; t <= nT; t++) {
72         res += (1.0 / nT) * SPFA(a);
73         a += V;
74     }
75     printf("%0.10lf\n", res);
76
77     return 0;
78 }

分析2  Simpson积分 + SPFA

  这道题要求连续性随机变量的数学期望.

  设当 $a = x$ 时, 最短路的长度是 $f_a$ .

  那么我们要求 $\frac{\int_0 ^ 1 f_a}{1 - 0}$ .

  Simpson积分套最短路.

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cctype>
 5 #include <cmath>
 6 #include <vector>
 7 #include <map>
 8 using namespace std;
 9 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
10 #define fore(it, x) for (register vector<Edge>::iterator it = g[x].begin(); it != g[x].end(); it++)
11 #define db double
12 inline int rd(void) {
13     int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1;
14     int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f;
15 }
16
17 const int N = 205;
18 const db INF = 1e20;
19
20 int n, m, S, T;
21 struct Edge {
22     int v; db x, y;
23     inline db d(db a) { return a * x + (1 - a) * y; }
24 };
25 vector<Edge> g[N];
26
27 inline void Init(int s, int t, db x, db y) {
28     g[s].push_back((Edge){t, x, y});
29     g[t].push_back((Edge){s, x, y});
30 }
31
32 int q[N], qh, qt; bool inq[N]; db dis[N];
33 map<db, db> val;
34
35 db SPFA(db a) {
36     if (val.count(a)) return val[a];
37     memset(q, 0, sizeof q), qh = qt = 0, memset(inq, false, sizeof inq), fill(dis + 1, dis + n + 1, INF);
38     q[++qt] = S, inq[S] = true, dis[S] = 0;
39     while (qh != qt) {
40         int x = q[qh = qh % n + 1];
41         fore(it, x)
42             if (dis[x] + it->d(a) < dis[it->v]) {
43                 dis[it->v] = dis[x] + it->d(a);
44                 if (!inq[it->v])
45                     q[qt = qt % n + 1] = it->v, inq[it->v] = true;
46             }
47         inq[x] = false;
48     }
49     return val[a] = dis[T];
50 }
51
52 inline db G(db L, db R) { return (R - L) * (SPFA(L) + SPFA(R) + 4 * SPFA((L+R)/2)) / 6; }
53 db Simpson(db L, db R) {
54     db M = (L+R)/2, RA = G(L, R), RL = G(L, M), RR = G(M, R);
55     return fabs(RA - RL - RR) < 1e-6 ? RL + RR : Simpson(L, M) + Simpson(M, R);
56 }
57
58 int main(void) {
59     #ifndef ONLINE_JUDGE
60         freopen("C.in", "r", stdin);
61     #endif
62
63     n = rd(), m = rd(), S = rd(), T = rd();
64     F(i, 1, m) {
65         int s = rd(), t = rd();
66         db x, y; scanf("%lf %lf", &x, &y);
67         Init(s, t, x, y);
68     }
69     printf("%0.10lf\n", Simpson(0, 1));
70
71     return 0;
72 }
时间: 2024-08-25 22:48:40

[XSY 1539] 狂飙突进的幻想乡的相关文章

幻想乡三连C——狂飙突进的幻想乡

题解: 不难发现,对于每一条从$S$到$T$的路径,设其$x.y$的和为$S_x.S_y$,其对答案的贡献是$a\cdot S_x+(1-a)\cdot S_y$,这是一个关于$a$的一次函数.而所有的路径就对应着许多$a\in [0,1]$直线,而不同$a$所对应的最短路长度恰好构成了这些直线的下凸壳,而求最短路的期望就是求上凸壳的积分(与坐标系横轴所夹面积),考虑到$n.m$很小,所以直接用一次函数不断拟合,每次求点值暴力跑一边最短路即可. #include<algorithm> #inc

红色的幻想乡

题目背景 蕾米莉亚的红雾异变失败后,很不甘心. 题目描述 经过上次失败后,蕾米莉亚决定再次发动红雾异变,但为了防止被灵梦退治,她决定将红雾以奇怪的阵势释放. 我们将幻想乡看做是一个n*m的方格地区,一开始没有任何一个地区被红雾遮盖.蕾米莉亚每次站在某一个地区上,向东南西北四个方向各发出一条无限长的红雾,可以影响到整行/整列,但不会影响到她所站的那个地区.如果两阵红雾碰撞,则会因为密度过大而沉降消失.灵梦察觉到了这次异变,决定去解决它.但在解决之前,灵梦想要了解一片范围红雾的密度.可以简述为两种操

[Zjoi2015]诸神眷顾的幻想乡

[Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1537  Solved: 892 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去,幽香为了方便,在这n块空地之间修建了n-1条

[luogu P3801] 红色的幻想乡 [线段树][树状数组]

题目背景 蕾米莉亚的红雾异变失败后,很不甘心. 题目描述 经过上次失败后,蕾米莉亚决定再次发动红雾异变,但为了防止被灵梦退治,她决定将红雾以奇怪的阵势释放. 我们将幻想乡看做是一个n*m的方格地区,一开始没有任何一个地区被红雾遮盖.蕾米莉亚每次站在某一个地区上,向东南西北四个方向各发出一条无限长的红雾,可以影响到整行/整列,但不会影响到她所站的那个地区.如果两阵红雾碰撞,则会因为密度过大而沉降消失.灵梦察觉到了这次异变,决定去解决它.但在解决之前,灵梦想要了解一片范围红雾的密度.可以简述为两种操

【BZOJ3926】[Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机

[BZOJ3926][Zjoi2015]诸神眷顾的幻想乡 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去,幽香为了方便,在这n块空地之间修建了n-1条边将它们连通起来.也就是说,这n块空地形成了一个树的结构. 有n个粉丝们来到了太阳花田上.为了表达对幽香生日的祝

BZOJ 4596: [Shoi2016]黑暗前的幻想乡

4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 408  Solved: 232[Submit][Status][Discuss] Description 四年一度的幻想乡大选开始了,最近幻想乡最大的问题是很多来历不明的妖 怪涌入了幻想乡,扰乱了幻想乡昔日的秩序.但是幻想乡的建制派妖怪(人类) 博丽灵梦和八云紫等人整日高谈所有妖怪平等,幻想乡多元化等等,对于幻想乡 目前面临的种种大问题却给不出合适的解

BZOJ 3926: [Zjoi20150]诸神眷顾的幻想乡

3926: [Zjoi20150]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 438  Solved: 273 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去,幽香为了方便,在这n块空地之间修

字符串(广义后缀自动机):BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡

3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 843  Solved: 510[Submit][Status][Discuss] Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n

bzoj3925: [Zjoi2015]地震后的幻想乡

Description 傲娇少女幽香是一个很萌很萌的妹子,而且她非常非常地有爱心,很喜欢为幻想乡的人们做一些自己力所能及的事情来帮助他们. 这不,幻想乡突然发生了地震,所有的道路都崩塌了.现在的首要任务是尽快让幻想乡的交通体系重新建立起来.幻想乡一共有n个地方,那么最快的方法当然是修复n-1条道路将这n个地方都连接起来. 幻想乡这n个地方本来是连通的,一共有m条边.现在这m条边由于地震的关系,全部都毁坏掉了.每条边都有一个修复它需要花费的时间,第i条边所需要的时间为ei.地震发生以后,由于幽香是