题目链接
大意:有个无向图,你从1出发,可以到任意联通的非怪物点,你至多可以选择一个可达的怪物房间使用魔法,传送到随机一个与怪物点相邻的点上,问你取得糖果的期望值(操作者足够聪明)。
思路:我们先dfs记录一下,不到怪物房间就能取到的糖果数量,这一部分肯定是可以直接拿的,剩下就是从那些相邻(意为不用经过怪物房间就能到的怪物房间)的怪物房间取一个最优的。
这个最优也是dfs记录从当前怪物点出发,随机下一个儿子,dfs计算能取到的糖果数量(同上面的dfs一样,不遇到怪物)加起来,除以儿子数量。
注意中间要记录访问过的点,不然会段错误哦。
细节见代码:

#include<bits/stdc++.h>

#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define LL long long
#define pii pair<int,int>
#define SZ(x) (int)x.size()
#define all(x) x.begin(),x.end()

using namespace std;

LL gcd(LL a, LL b) {return b ? gcd(b, a % b) : a;}
LL lcm(LL a, LL b) {return a / gcd(a, b) * b;}
LL powmod(LL a, LL b, LL MOD) {LL ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
const int N = 1e6 + 3;
const LL mod = 1e9 + 7;
int t,n,m,k;
int c[N];
vector<int>v[N],q;
int vis[N],ans;
void dfs(int now,int pre){
    vis[now]=1;
    ans++;
    for(auto k:v[now]){
        if(k==pre||vis[k])continue;
        if(c[k])vis[k]=1,q.pb(k);
        else{
            dfs(k,now);
        }
    }
}
vector<int>res;
int mid[N];
int bfs(int now,int pre){
    int ans=1;
    mid[now]=1;
    res.pb(now);
    for(auto k:v[now]){
        if(k==pre||c[k]||vis[k]||mid[k])continue;
        ans+=bfs(k,now);
    }
    return ans;
}
int main() {
    for(scanf("%d",&t);t;t--){
        q.clear();
        scanf("%d%d%d",&n,&m,&k);ans=0;
        for(int i=1;i<=n;i++)v[i].clear(),c[i]=0,vis[i]=0,mid[i]=0;
        for(int i=1;i<=m;i++){
            int s,t;
            scanf("%d%d",&s,&t);
            v[s].pb(t);
            v[t].pb(s);
        }
        for(int i=1;i<=k;i++){
            int s;
            scanf("%d",&s);
            c[s]=1;
        }
        dfs(1,0);
        LL tot=0;
        double ANS=ans;
        for(auto k:q){
            tot=0;
            int sz=SZ(v[k]);
            if(!sz)continue;
            for(auto ne:v[k]){
                res.clear();
                if(vis[ne]||c[ne])continue;

                tot+=bfs(ne,k);
                for(auto X:res)mid[X]=0;
            }
            double res=1.0*tot/sz;
            ANS=max(ANS,res+ans);
        }
        printf("%.6f\n",ANS);
    }
	return 0;
}