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; }
没有人不辛苦,只有人不喊疼