洛谷P4581 [BJOI2014]想法(玄學演算法,拓撲排序)
阿新 • • 發佈:2019-01-05
蘿蔔大毒瘤
題意可以簡化成這樣:給一個DAG,求每個點能夠從多少個入度為\(0\)的點到達(記為\(k\))。
一個隨機做法:給每個入度為\(0\)的點隨機一個權值,在DAG上求出每個點能夠返回到的入度為\(0\)的點的最小權值,那麼這個權值的期望是\(\frac{\text{隨機值域}}{k}\)。多選幾套隨機權值(蒟蒻選了一百次),跑出來的平均值即可輸出。
實在是太玄學了。
#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; }