1. 程式人生 > >洛谷P4581 [BJOI2014]想法(玄學演算法,拓撲排序)

洛谷P4581 [BJOI2014]想法(玄學演算法,拓撲排序)

洛谷題目傳送門

蘿蔔大毒瘤

題意可以簡化成這樣:給一個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;
}