jsk-41402 ICPC Shenyang Pre E

jsk-41402 ICPC Shenyang Pre E

题意

link

给一个图,有些点是坏的,有些点是好的。主角自由行动,但会有意识地尽量走多的好点。

每个好点可以取走一个收益,第一次访问到坏点,会等概率跳到与之相邻的某一点。

注意第二次走到坏点就直接结束过程,或者没有更多收益的时候,可以主动结束过程。

起点是1,求收益的期望。

思路

相互连通的好点必然可以缩成一块。当缩成一块的时候,第一块的收益必定取完。

而人只能走一次坏点,有些选择是更优的(期望更大),所以有意识的主角只会走期望最大的方案。(如果有多个期望相等的情况,其实仔细一想,等概率去走的时候,收益的期望是一样的,所以只要知道最大是多少即可)

有了以上的理解,只要知道怎么算第一个走到的点的期望怎么算就好了。无非就是所链接块的收益求和乘以概率即可。

有些细节:

起点所在的块的收益是必被取过的,所以如果跳到的点是回到第一块了,收益是0。

如果跳到的点也是坏点,收益是0。

img1

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
* solution for https://nanti.jisuanke.com/t/41402
*
*/
//#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <tuple>

#define _debug(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 59;
const int MAXM = 2e5 + 59;
const ll MOD = 998244353;
const ll INF = 0x0f0f0f0f;

int fa[MAXN];
int sz[MAXN];

int findf(int x) {
if (x == fa[x])return x;
else {
sz[fa[x]] += sz[x];
sz[x] = 0;
return fa[x] = findf(fa[x]);
}
}

void mergf(int x, int y) {
int fx = findf(x);
int fy = findf(y);
if (fx == fy)return;
if (sz[fx] <= sz[fy]) {
sz[fx] += sz[fy];
sz[fy] = 0;
fa[fy] = fx;
} else {
sz[fy] += sz[fx];
sz[fx] = 0;
fa[fx] = fy;
}
}


int Kase;
int n, m, k;
pair<int, int> e[MAXM];
int a[MAXN];
bool tag[MAXN];
bool vis[MAXN];
vector<int> g[MAXN];

int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);

cin >> Kase;
while (Kase--) {
cin >> n >> m >> k;
for (int i = 1; i <= n; ++i) {
fa[i] = i;
sz[i] = 1;
tag[i] = false;
vis[i] = false;
g[i].clear();
}
for (int i = 1; i <= m; ++i) {
cin >> e[i].first >> e[i].second;
}
for (int i = 1; i <= k; ++i) {
cin >> a[i];
tag[a[i]] = true;
sz[a[i]] = 0;
}
for (int i = 1; i <= m; ++i) {
if (tag[e[i].first] == 0 && tag[e[i].second] == 0) {
mergf(e[i].first, e[i].second);
}
}
for (int u, v, i = 1; i <= m; ++i) {
tie(u, v) = e[i];

v = findf(v);
u = findf(u);

if (tag[u] || tag[v]) {
g[u].emplace_back(v);
g[v].emplace_back(u);
}
}

int start = findf(1);
double ans = sz[start];
double tmp = 0;

for (auto u:g[start]) {
if (vis[u])continue;
else vis[u] = true;

double sum = 0;
for (auto v:g[u])if (v != start)sum += sz[v];
sum /= 1.0 * g[u].size();

if (sum > tmp) tmp = sum;
}
ans += tmp;
printf("%.6f\n", ans);
}

return 0;
}
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×