zoukankan      html  css  js  c++  java
  • bzoj 1778: [Usaco2010 Hol]Dotp 驱逐猪猡

    Description

    奶牛们建立了一个随机化的臭气炸弹来驱逐猪猡。猪猡的文明包含1到N (2 <= N <= 300)一共N个猪城。这些城市由M (1 <= M <= 44,850)条由两个不同端点A_j和B_j (1 <= A_j<= N; 1 <= B_j <= N)表示的双向道路连接。保证城市1至少连接一个其它的城市。一开始臭气弹会被放在城市1。每个小时(包括第一个小时),它有P/Q (1 <= P <=1,000,000; 1 <= Q <= 1,000,000)的概率污染它所在的城市。如果这个小时内它没有污染它所在的城市,那麽它随机地选择一条道路,在这个小时内沿着这条道路走到一个新的城市。可以离开这个城市的所有道路被选择的概率均等。因为这个臭气弹的随机的性质,奶牛们很困惑哪个城市最有可能被污染。给定一个猪猡文明的地图和臭气弹在每个小时内爆炸的概率。计算每个城市最终被污染的概率。如下例,假设这个猪猡文明有两个连接在一起的城市。臭气炸弹从城市1出发,每到一个城市,它都有1/2的概率爆炸。 1--2 可知下面这些路径是炸弹可能经过的路径(最后一个城市是臭气弹爆炸的城市): 1: 1 2: 1-2 3: 1-2-1 4: 1-2-1-2 5: 1-2-1-2-1 ... 要得到炸弹在城市1终止的概率,我们可以把上面的第1,第3,第5……条路径的概率加起来,(也就是上表奇数编号的路径)。上表中第k条路径的概率正好是(1/2)^k,也就是必须在前k-1个回合离开所在城市(每次的概率为1 - 1/2 = 1/2)并且留在最后一个城市(概率为1/2)。所以在城市1结束的概率可以表示为1/2 + (1/2)^3 + (1/2)^5 + ...。当我们无限地计算把这些项一个个加起来,我们最后会恰好得到2/3,也就是我们要求的概率,大约是0.666666667。这意味着最终停留在城市2的概率为1/3,大约为0.333333333。

    Input

    * 第1行: 四个由空格隔开的整数: N, M, P, 和 Q * 第2到第M+1行: 第i+1行用两个由空格隔开的整数A_j和B_j表示一条道路。

    Output

    * 第1到第N行: 在第i行,用一个浮点数输出城市i被摧毁的概率。误差不超过10^-6的答桉会 被接受(注意这就是说你需要至少输出6位有效数字使得答桉有效)。
    solution
    再不写题解可能又忘了....
    设f[i]为在i爆炸的概率   与i相连的点为j
    f[i]=   f[j]/(p/q)      *     (1-p/q)          *   1/outdegree[j]        *        p/q
             在j点的概率      j点不爆炸的概率         不爆炸走到j点                   在i点爆炸
        =  f[j] * (1-p/q) * (1/outdegree[j])   (化简之后的式子)
    高斯解方程即可
      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #define mem(a,b) memset(a,b,sizeof(a))
      5 using namespace std;
      6 const double qqq=1e-8;
      7  
      8 double abss(double x)
      9 {
     10     if(x<0)
     11       return -x;
     12     return x;
     13 }
     14 
     15 void swap(double &x,double &y)
     16 {
     17     double temp;
     18     temp=x;
     19     x=y;
     20     y=temp;
     21 }
     22  
     23 struct son
     24 {
     25     int v,next;
     26 };
     27 son a1[100001];
     28 int first[100001];
     29 int e;
     30  
     31 void addbian(int u,int v)
     32 {
     33     a1[e].v=v;
     34     a1[e].next=first[u];
     35     first[u]=e++;
     36 }
     37  
     38 int n,m,p,q;
     39 int u,o;
     40 double degree[301];
     41 double a[301][301];
     42 double ans[301];
     43 double b[301];
     44  
     45 void out11()
     46 {
     47     for(int i=1;i<=n;i++)
     48       printf("%lf ",degree[i]);
     49     printf("
    ");
     50     for(int i=1;i<=n;i++)
     51     {
     52         for(int j=1;j<=n;j++)
     53           printf("%.3lf ",a[i][j]);
     54         printf("%.3lf
    ",b[i]);
     55     }
     56     printf("
    ");
     57 }
     58  
     59 void gaos()
     60 {
     61     int now=1;
     62     for(int k=1;k<n;++k,++now)
     63     {
     64         int order=k;
     65         for(int i=k+1;i<=n;i++)
     66           if(abss(a[order][k])<abss(a[i][k]))
     67             order=i;
     68         if(order!=k)
     69         {
     70             for(int i=k;i<=n;i++)
     71               swap(a[now][i],a[order][i]);
     72             swap(b[now],b[order]);
     73         }
     74         if(!a[now][k])
     75         {
     76             --now;
     77             continue;
     78         }
     79         double temp;
     80         for(int i=now+1;i<=n;i++)
     81         {
     82             temp=a[i][k]/a[now][k];
     83             for(int j=k;j<=n+1;j++)
     84               a[i][j]-=temp*a[k][j];
     85             b[i]-=temp*b[k];
     86         }
     87     }
     88     
     89     for(int i=n;i>=1;--i)
     90     {
     91         for(int j=n;j>=i+1;--j)
     92           b[i]-=a[i][j]*ans[j];
     93         ans[i]=b[i]/a[i][i];
     94     }
     95     for(int k=1;k<=n;++k)
     96         printf("%.9lf
    ",ans[k]);
     97 }
     98  
     99 int main(){
    100     freopen("dotp.in","r",stdin);
    101     freopen("dotp.out","w",stdout);
    102     mem(first,-1);
    103     scanf("%d%d%d%d",&n,&m,&p,&q);
    104     for(int i=1;i<=m;i++)
    105     {
    106         scanf("%d%d",&u,&o);
    107         addbian(u,o);
    108         addbian(o,u);
    109         ++degree[o];
    110         ++degree[u];
    111     }
    112     for(int i=1;i<=n;i++)
    113       a[1][i]=1;
    114     b[1]=1;
    115     int temp;
    116     double qq=1-(double)p/q;
    117     for(int i=2;i<=n;i++)
    118     {
    119         a[i][i]=1;
    120         for(int j=first[i];j!=-1;j=a1[j].next)
    121         {
    122             temp=a1[j].v;
    123             a[i][temp]=-(1.0/degree[temp])*qq;
    124         }
    125         b[i]=0;
    126     }
    127     gaos();
    128     
    129     //while(1);
    130     return 0;
    131 }
    code
  • 相关阅读:
    系统架构师学习笔记_第十一章(下)
    通过IronRuby和C#学习RUBY系列[0]
    TIPS to comment your code
    超级简单:DIV布局
    js 查询XML数据添加到HTML select控件
    《架构之美》读书笔记(一)
    18个不常见的C#关键字,您使用过几个?
    如何成为人尽皆知的C#开发人员
    实现Visual Studio 2010一个很简单的很酷的扩展
    一种简单的直观的高效的权限设计
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7359880.html
Copyright © 2011-2022 走看看