盒子之间的开启关系 用图的方式呈现 就是一片环
最终所有成功开启 则每一颗环都成功开启
所以求出每个环放k个点成功的概率
之后依次枚举每一颗环 及其内部选择点数与在之前的环中选择点数 再乘上对应概率
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef double db;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=310;
int last[N],ecnt;
struct EDGE{int to,nt;}e[N];
inline void add(int u,int v)
{e[++ecnt]=(EDGE){v,last[u]};last[u]=ecnt;}
int Fa[N];
int find(int x)
{return Fa[x]==x ? x : Fa[x]=find(Fa[x]);}
bool book[N];
int dep[N],size[N];
int len;
void dfs(int u)
{
size[u]=book[u]=1;
for(int i=last[u],v;i;i=e[i].nt)
{
if(book[v=e[i].to])
{
len=dep[u];
continue;
}
dep[v]=dep[u]+1;
dfs(v);
size[u]+=size[v];
}
}
int st[N],num[N],top;
db p[N][N],f[N],g[N],tmp[N][N];
int main()
{
register int T=read(),i,j,k,x;
while(T--)
{
int n=read(),K=read();
for(i=1;i<=n;++i) Fa[i]=i;
ecnt=0;memset(last,0,sizeof(last));
for(i=1;i<=n;++i)
x=read(),add(i,x),
Fa[find(x)]=find(i);
if(K==0){puts("0.000000000");continue;}
else if(K==n){puts("1.000000000");continue;}
top=0;
for(i=1;i<=n;++i)
if(find(i)==i)
st[++top]=i;
memset(book,0,sizeof(book));
for(i=1;i<=top;++i)
dep[st[i]]=1,dfs(st[i]),num[i]=len;
db now;
for(i=1;i<=top;++i)
{
for(j=0,now=1;j<=size[st[i]]-num[i];++j,now*=(1.0*(size[st[i]]-num[i]-j+1)/(size[st[i]]-j+1)))
p[i][j]=1-now;
for(j=size[st[i]]-num[i]+1;j<=size[st[i]];++j)
p[i][j]=1;
}
memset(f,0,sizeof(f));
f[0]=1;
int s,t(0);
for(i=1;i<=top;++i)
{
memcpy(g,f,sizeof(f));
memset(f,0,sizeof(f));
s=size[st[i]];
tmp[0][0]=1;
for(j=1;j<=s;++j)
tmp[j][0]=tmp[j-1][0]*(s-j+1)/(s+t-j+1);
for(j=1;j<=t;++j)
tmp[0][j]=tmp[0][j-1]*(t-j+1)/(s+t-j+1);
for(j=1;j<=s;++j)
for(k=1;k<=t;++k)
tmp[j][k]=tmp[j-1][k]*(s-j+1)/(s+t-k-j+1)+tmp[j][k-1]*(t-k+1)/(s+t-k-j+1);
for(j=1;j<=s;++j)
for(k=i-1;k<=t;++k)
f[k+j]+=p[i][j]*g[k]*tmp[j][k];
t+=s;
}
printf("%.9lf\n",f[K]);
}
return 0;
}