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;
  }
      
                  
      
View Code

 

posted @ 2015-08-01 07:23  maijing  阅读(285)  评论(0编辑  收藏  举报