2019沈阳网络赛 Dudu's maze (并查集)

首先这道题他要求以最优的方法,那么显然我们发现,因为路可以随便走,我们从1开始,首先肯定可以取完与他连通的candy。

之后我们可以选择去哪个怪物房,因为我们只能用一次传送门,因此其实只能另外再取另一个连通块,并且必须要通过和1这个块相连的怪物房。

对于一个怪物房,我们随机进入一个邻边,只是一个简单的期望问题。最后对于每个怪物房取max即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int inf=0x3f3f3f3f;
const int N=1e5+10;
const int mod=1e9+7;
vector<int> g[N];
int n,m,k;
int p[N];
int cnt[N];
int d[N],sign[N];
int num[N];
void init(){
    int i;
    memset(cnt,0,sizeof cnt);
    memset(sign,0,sizeof sign);
    for(i=1;i<=n;i++){
        g[i].clear();
        p[i]=i;
        d[i]=1;
    }
}
int find(int x){
    if(x!=p[x]){
        p[x]=find(p[x]);
    }
    return p[x];
}
int main(){
    //ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--){
        scanf("%d%d%d",&n,&m,&k);
        init();
        int i,j;
        while(m--){
            int a,b;
            scanf("%d%d",&a,&b);
            g[a].push_back(b);
            g[b].push_back(a);
        }
        int idx=0;
        for(i=1;i<=k;i++){
            int x;
            cin>>x;
            sign[x]=1;
            num[++idx]=x;
        }
        for(i=1;i<=n;i++){
            if(!sign[i]){
                for (auto x:g[i]){
                    if(sign[x])
                        continue;
                    int pa=find(i);
                    int pb=find(x);
                    if(pa!=pb){
                        p[pa]=pb;
                        d[pb]+=d[pa];
                        d[pa]=0;
                    }
                }
            }
        }
        int sum=d[find(1)];
        double res=0;
        for(i=1;i<=n;i++){
            if(sign[i]){
                int ok=0;
                double tmp=0;
                for(auto x:g[i]){
                    int pa=find(x);
                    if(pa==find(1)){
                        ok=1;
                        break;
                    }
                }
                if(ok){
                    int ll=0;
                    for(auto x:g[i]){
                        ll++;
                        if(sign[x])
                            continue;
                        if(find(x)==find(1))
                            continue;
                        tmp+=d[find(x)];

                    }
                    tmp/=ll;
                    res=max(res,tmp);
                }
            }
        }
        printf("%.6f\n",sum+res);
    }
    return 0;
}
View Code

 

posted @ 2020-08-18 14:18  朝暮不思  阅读(130)  评论(0编辑  收藏  举报