NOI2012 迷失游乐园
http://www.lydsy.com/JudgeOnline/problem.php?id=2878
比较容易的概率题。
Case1~5:
这是一棵树。
我们求出每个点i度数du[i],只走子树的期望距离g[i]和不走子树的期望距离f[i],这比较好求。
然后累加即可。
Case6~10:
图中有一个环,然后环上的点都是一棵树的根。
对于每棵树,我们同样求出每个点i度数du[i],只走子树的期望距离g[i]。
那么怎么求不走子树的期望距离f[i]呢?
我们先求环上的点的f[i]吧。
我们枚举环上的点i,再枚举环上的另一个点j,求出i能到到j的距离概率和距离(有2个方向,都一样),然后f[i]+=概率*(距离+g[j])。
现在每棵树的根节点的不走子树的期望距离f[i]已经算出来了,然后树中的点f[i]也就很容易了。
然后累加即可。
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> #include<deque> #include<cctype> #include<climits> #include<complex> //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define re(i,a,b) for(i=a;i<=b;i++) #define red(i,a,b) for(i=a;i>=b;i--) #define fi first #define se second #define m_p(a,b) make_pair(a,b) #define SF scanf #define PF printf #define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-9; inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;} const DB Pi=acos(-1.0); inline void clear(vector<int> *A,int a,int b){int i,j;A->clear();re(i,0,a)re(j,0,b)A[i].push_back(0);} inline int gint() { int res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } inline LL gll() { LL res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } const int maxN=100000; int N,M; int now,first[maxN+100]; struct Tedge{int v,next,dis;}edge[2*maxN+100]; DB ans; int cnt,root[maxN+100]; int id[maxN+100]; DB lon[maxN+100],val[maxN+100],h[maxN+100]; inline void addedge(int u,int v,int dis) { now++; edge[now].v=v; edge[now].dis=dis; edge[now].next=first[u]; first[u]=now; } int du[maxN+100],fa[maxN+100]; DB g[maxN+100],f[maxN+100]; int head,tail,que[maxN+100]; inline void BFS(int S) { int i,j; que[head=tail=1]=S; fa[S]=0; du[S]=0; while(head<=tail) { int u=que[head++],v; for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)if(v!=fa[u] && id[v]==0) { fa[que[++tail]=v]=u; du[u]++; du[v]=1; } } red(j,tail,1) { int u=que[j],v,dis; g[u]=0.0; for(i=first[u],v=edge[i].v,dis=edge[i].dis;i!=-1;i=edge[i].next,v=edge[i].v,dis=edge[i].dis)if(v!=fa[u] && id[v]==0)g[u]+=DB(dis)+g[v]; int t=(u==S)?du[u]:du[u]-1; if(t!=0)g[u]/=DB(t); } } inline void BFS2(int S) { int i,j; que[head=tail=1]=S; fa[S]=0; while(head<=tail) { int u=que[head++],v; for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)if(v!=fa[u] && id[v]==0) fa[que[++tail]=v]=u; } re(j,1,tail) { int u=que[j],v,dis; DB sum=0.0; for(i=first[u],v=edge[i].v,dis=edge[i].dis;i!=-1;i=edge[i].next,v=edge[i].v,dis=edge[i].dis)if(v!=fa[u] && id[v]==0)sum+=DB(dis)+g[v]; if(M==N && id[u]!=0) sum+=f[u]+f[u]; else sum+=f[u]; int t=du[u]-1; for(i=first[u],v=edge[i].v,dis=edge[i].dis;i!=-1;i=edge[i].next,v=edge[i].v,dis=edge[i].dis)if(v!=fa[u] && id[v]==0) { f[v]=sum-DB(dis)-g[v]; if(t!=0)f[v]/=DB(t); f[v]+=DB(dis); } } } int vis[maxN+100]; int top,sta[maxN+100],last[maxN+100]; inline void DFS() { mmst(vis,0); mmst(fa,0); vis[sta[top=1]=1]=1; last[1]=first[1]; while(top>=1) { int u=sta[top],i=last[top],v; for(v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v) { if(!vis[v]) { vis[sta[++top]=v]=1; last[top]=first[v]; fa[v]=u; last[top-1]=edge[i].next; break; } if(v!=fa[u] && vis[v]) { while(sta[top]!=v)root[++cnt]=sta[top--]; root[++cnt]=v; return; } } if(i==-1)vis[sta[top--]]=0; } } int main() { freopen("park.in","r",stdin); freopen("park.out","w",stdout); int i,j; N=gint();M=gint(); mmst(first,-1);now=-1; re(i,1,M) { int x=gint(),y=gint(),dis=gint(); addedge(x,y,dis); addedge(y,x,dis); } if(M==N-1) { BFS(1); mmst(fa,0); f[1]=0.0;BFS2(1); ans=0.0; re(i,1,N) { int t=(i==1)?du[i]:du[i]-1; ans+=g[i]*(DB(t)/DB(du[i]))+f[i]*(1.0-DB(t)/DB(du[i])); } ans/=DB(N); PF("%0.5lf\n",ans); return 0; } else { DFS(); re(i,1,cnt)id[root[i]]=i; re(i,1,cnt)BFS(root[i]); #define next(i) (i%cnt+1) #define qian(i) (((i-2)%cnt+cnt)%cnt+1) re(j,1,cnt) { int i,v,dis; for(i=first[root[j]],v=edge[i].v,dis=edge[i].dis;i!=-1;i=edge[i].next,v=edge[i].v,dis=edge[i].dis)if(v==root[next(j)]){lon[j]=DB(dis);break;} } re(i,1,cnt) { h[i]=0.0; int p=i; DB gailv=1e10,t=0.0; while(1) { if(p==i) gailv/=2.0; else gailv/=DB(du[root[p]]+1); t+=lon[p]; p=next(p); if(next(p)!=i) h[i]+=gailv*(DB(du[root[p]])/DB(du[root[p]]+1))*(t+g[root[p]]); else { h[i]+=gailv*(t+g[root[p]]); break; } } p=i; gailv=1e10; t=0.0; while(1) { if(p==i) gailv/=2.0; else gailv/=DB(du[root[p]]+1); t+=lon[qian(p)]; p=qian(p); if(qian(p)!=i) h[i]+=gailv*(DB(du[root[p]])/DB(du[root[p]]+1))*(t+g[root[p]]); else { h[i]+=gailv*(t+g[root[p]]); break; } } h[i]/=1e10; } mmst(fa,0); re(i,1,cnt)du[root[i]]+=2,f[root[i]]=h[i],BFS2(root[i]); ans=0.0; re(i,1,N) { int t=(id[i]!=0)?du[i]-2:du[i]-1; ans+=g[i]*(DB(t)/DB(du[i]))+f[i]*(1.0-DB(t)/DB(du[i])); } ans/=DB(N); PF("%0.5lf\n",ans); return 0; } return 0; }