洛谷題目傳送門c++
蘿蔔大毒瘤spa
題意能夠簡化成這樣:給一個DAG,求每一個點可以從多少個入度爲\(0\)的點到達(記爲\(k\))。code
一個隨機作法:給每一個入度爲\(0\)的點隨機一個權值,在DAG上求出每一個點可以返回到的入度爲\(0\)的點的最小權值,那麼這個權值的指望是\(\frac{\text{隨機值域}}{k+1}\)。多選幾套隨機權值(蒟蒻選了一百次),跑出來的平均值便可輸出。ip
實在是太玄學了。get
#include<bits/stdc++.h> #define LL unsigned long long #define RG register #define R RG int #define G if(++ip==ie)if(fread(ip=buf,1,SZ,stdin)) #define F(S) if(freopen(S".in","r",stdin));if(freopen(S".out","w",stdout)) using namespace std; const int SZ=1<<18,N=1e6+1,S=50,T=2; char buf[SZ],*ie=buf+SZ,*ip=ie-1; inline int in(){ G;while(*ip<'-')G; R x=*ip&15;G; while(*ip>'-'){x*=10;x+=*ip&15;G;} return x; } inline int Min(R x,R y){ return x<y?x:y; } int f[N][S],c[N][2]; double ans[N]; int main(){ srand(20020307); R n=in(),m=in(); for(R i=m+1;i<=n;++i) c[i][0]=in(),c[i][1]=in(); for(R t=T;t;--t){ for(R i=1;i<=m;++i) for(R j=0;j<S;++j) f[i][j]=rand(); for(R i=m+1;i<=n;++i) for(R j=0;j<S;++j) ans[i]+=f[i][j]=Min(f[c[i][0]][j],f[c[i][1]][j]); } for(R i=m+1;i<=n;++i) printf("%d\n",(int)(RAND_MAX/ans[i]*S*T-0.5)); return 0; }