题目链接:https://nanti.jisuanke.com/t/41402
题解:首先和1联通的糖果屋都能到达,其他不能到达的肯定被恶魔屋挡住了,那就在挡住的所以恶魔屋中选择一个最优的就可以了,怎么算最优呢,因为到达恶魔屋之后,下一个地方是随机的,所以就看 和恶魔屋的连接的每一个联通块的糖果屋的总和 / 下一个地方的数目,计算得到一个最大的即可,在跑完每个联通块的时候,接着标记该联通块的每个点
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
struct edge {
int to, nex;
}e[N * 2 * 2];
int n, m, k;
int visp[N];
int head[N], len;
int vis[N], book[N];
int vv[N];
void init() {
for(int i = 0; i <= n; i++) {
head[i] = -1;
visp[i] = 0;
vis[i] = 0;
book[i] = -1;
vv[i] = 0;
}
len = 0;
}
void add(int x, int y) {
e[len].to = y;
e[len].nex = head[x];
head[x] = len++;
}
double ans, num;
queue<int> q;
int cnt;
void dfs1(int x) {
cnt++;
vis[x] = 1;
int to;
for(int i = head[x]; i != -1; i = e[i].nex) {
to = e[i].to;
if(vis[to]) continue;
if(visp[to]) {
if(vv[to] == 0) q.push(to), vv[to] = 1;
continue;
}
dfs1(to);
}
}
void dfs2(int x) {
cnt++;
vis[x] = 1;
int to;
for(int i = head[x]; i != -1; i = e[i].nex) {
to = e[i].to;
if(vis[to]) continue;
if(visp[to]) {
continue;
}
dfs2(to);
}
}
void dfs3(int x, int val) {
book[x] = val;
int to;
for(int i = head[x]; i != -1; i = e[i].nex) {
to = e[i].to;
if(visp[to] || book[to] != -1) {
continue;
}
dfs3(to, val);
}
}
int main() {
int T;
int x, y;
double maxx, tmp;
int num;
scanf("%d", &T);
while(T--) {
scanf("%d %d %d", &n, &m, &k);
init();
q.empty();
for(int i = 1; i <= m; i++) {
scanf("%d %d", &x, &y);
add(x, y);
add(y, x);
}
for(int i = 1; i <= k; i++) {
scanf("%d", &x);
visp[x] = 1;
}
ans = 0;
num = 0;
maxx = 0;
cnt = 0;
if(visp[1] == 0) {
dfs1(1);
ans = cnt;
dfs3(1, 0);
} else {
q.push(1);
book[1] = 0;
}
int to;
while(!q.empty()) {
x = q.front();
q.pop();
tmp = 0;
num = 0;
for(int i = head[x]; i != -1; i = e[i].nex) {
to = e[i].to;
if(visp[to]) {
num++;
continue;
}
cnt = 0;
if(book[to] == -1) {
dfs2(to);
dfs3(to, cnt);
}
else cnt = book[to];
num += 1;
tmp += cnt;
}
if(num > 0 && tmp / num > maxx) {
maxx = tmp / num;
}
}
printf("%.6f\n", ans + maxx);
}
return 0;
}
/*
6 10 1
1 2
1 3
1 4
2 3
3 4
2 5
3 5
3 6
4 6
5 6
3
*/