UAPC 2011 H World domination
問題
n個の敵がいる。
それぞれの敵は、どれか一人の他の敵の、弱点になるパーツを持っている。
パーツは一人一つで、弱点がかぶっていることはない。
弱点のパーツを持っていないときに、その敵を1ターンで倒せる確率はp[i],
持っているときにその敵を1ターンで倒せる確率はw[i]である。
どのような順序で敵を倒せば、かかるターン数の期待値が最小になるか。
期待値の最小値を求めよ。また、そのような期待値を実現する倒し方の総数を求めよ。
方針
弱点の関係を表すグラフはいくつかの輪からなるものである。
輪の一体の敵を倒したあとその輪の中で、弱点ではない別の敵を倒す意味はない。
(p[i]<w[i]だから)
なので、最初の一体を決めたら、その輪の敵全員を倒すのにかかるターンの期待値は求まる。
これを全ての輪について求め足し合わせて、ついでにその場合の数も数える。
ソースコード
const int mod=100000007; int n,e[100],C[101][101]; double p[100],q[100]; bool v[100]; void _(vi &tmp,int c){ v[c]=1; tmp.pb(c); if(!v[e[c]])_(tmp,e[c]); } double rec(int c,int s,bool start=1){ if(start)return 1/p[c]+rec(e[c],s,0); return 1/q[c]+(e[c]!=s?rec(e[c],s,0):0); } int main(){ rep(i,101)rep(j,i+1)C[i][j]=(i==0||j==i?1:C[i-1][j]+C[i-1][j-1])%mod; while(cin>>n,n){ rep(i,n){ int t; cin>>p[i]>>t>>q[i]; e[t]=i; v[i]=0; } vector<vi> vs; rep(i,n)if(!v[i]){ vi tmp; _(tmp,i); vs.pb(tmp); } ll comb=1; double ex=0; rep(i,vs.size()){ double mn=1e9,tmp; int cnt=0; rep(j,vs[i].size()){ tmp=rec(vs[i][j],vs[i][j]); if(tmp+1e-9<mn)mn=tmp, cnt=0; if(abs(tmp-mn)<1e-9)cnt++; } ex+=mn; (comb*=cnt*C[n][vs[i].size()])%=mod; n-=vs[i].size(); } printf("%.9f %d\n",ex,(int)comb); } return 0; }