zoukankan      html  css  js  c++  java
  • [codeforces113D]Museum

    D. Museum
    time limit per test:
    2 seconds
    memory limit per test:
    256 megabytes
    input:
    standard input
    output:
    standard output

    One day as Petya and his friend Vasya were having one of their numerous trips, they decided to visit a museum castle. The museum has a specific shape: it consists of n rooms connected with m corridors so that one can access any room from any other one.

    After the two friends had a little walk around the museum, they decided to split and watch the pieces of art each of them found interesting. They agreed to meet in one of the rooms at six p.m. However, they forgot one quite essential thing: they didn't specify the place to meet and when the time came, they started to rush about the museum looking for each other (they couldn't call each other as roaming made a call's cost skyrocket).

    Yet, even despite the whole rush, they couldn't get enough of the pieces of art, that's why each of them has the following strategy: each minute he make a decision where to go — with probability pi he doesn't move to any other place during this minute (i.e. he stays in the room). With probability 1 - pi he equiprobably choose one of the adjacent rooms and went there along the corridor. Here i is the ordinal number of the current room. Building was expensive in ancient times, that's why each corridor connected two different rooms, and any two rooms had no more than one corridor between them.

    The boys act simultaneously. As the corridors are dark, it is impossible to meet there; however, one can walk along the corridors in both directions (besides, the two boys can be going through the same corridor simultaneously without meeting). The boys act like that until they meet each other. More formally, the two friends meet when at some moment of time both of them decided to appear in the same room.

    For each room find the probability that the boys will meet there considering that at 6 p.m. they are positioned in rooms a and bcorrespondingly.

    Input

    The first line contains four integers: n (1 ≤ n ≤ 22), representing the numbers of rooms; m , representing the number of corridors; a, b (1 ≤ a, b ≤ n), representing the numbers of Petya's and Vasya's starting rooms correspondingly.

    Next m lines contain pairs of numbers — the numbers of rooms connected by a corridor. Next n lines contain probabilities pi(0.01 ≤ pi ≤ 0.99) with the accuracy of up to four digits after the decimal point — the probability to stay in room i.

    It is guaranteed that every room can be reached from every other room by corridors.

    Output

    In the only line print n space-separated numbers, the i-th number should represent the probability that the friends meet in the i-th room with absolute or relative error of no more than 10 - 6.

    Examples
    input
    2 1 1 2
    1 2
    0.5
    0.5
    output
    0.5000000000 0.5000000000 
    input
    4 4 1 2
    1 2
    2 3
    3 4
    4 1
    0.5
    0.5
    0.5
    0.5
    output
    0.3333333333 0.3333333333 0.1666666667 0.1666666667 
    Note

    In the first sample the museum is symmetric. That means the probabilities to meet in rooms 1 and 2 are equal. And their sum equals to one. So, each probability equals 0.5.

    题解

    第一次来cf做题,98个测试点真的是吓到我了

    这个题和"hnoi2013游走"比较像,都是无向图瞎跑处理问题

    但不一样的是,这个题没有固定的终点

    又观察到n比较小,所以我们不妨枚举终点,即对每个点t来说,枚举t,计算t为终点时两个人在t点会面的概率

    设在i点停留的概率为p[i],i点出度为du[i]设从i点走向某一点的概率为k[i],则k[i]=(1-p[i])/du[i]

    设这两个人一个人在i,一个人在j,则有如下情况:

    1°:i==t&&j==t,则f[i][j]=1;

    2°:i==j&&i!=t,则f[i][j]=0;

    如果均不满足,则

    3°f[i][j]=p[i]*p[i]*f[i][j]+k[i]*p[j]*∑{f[u][j],i有边连向u}+p[i]*k[j]*∑{f[i][v],j有边连向v}+k[i]*k[j]*∑{f[u][v],i有边连向u,j有边连向v}

    好长一大串啊注意,f[u][j],f[i][v]和f[u][v]可能满足上述条件1°和2°,要特判并处理

    这样本题就变成了一个熟悉的问题:解方程组,也就是说高斯消元怎么又是高斯消元啊啊啊

    我们的未知量,就是这里的f[i][j]

    但是f数组没有一个固定的顺序,所以我们先给每一个数对{i,j(i!=j)}编号,设共有cnt对

    设点对{S,T}的编号是num,则对于每个点t来说,答案就是对应编号方程的解了(ans[t]=A[num][cnt+1])

    最后,注意特判,即两人一开始就在一间屋子时,除了那个屋子的答案是1,其他屋子都是0,输出就好.

    代码见下:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 using namespace std;
     6 const int N=50;
     7 const int M=(N-1)*N>>1;
     8 int n,m,S,T,du[N],adj[N],e;
     9 double A[M][M],p[N],k[N],ans[N];
    10 struct node{int qi,zhong,next;}s[M<<1];
    11 inline void add(int qi,int zhong)
    12 {s[++e].zhong=zhong;s[e].qi=qi;s[e].next=adj[qi];adj[qi]=e;}
    13 int num[N][N],cnt,f[N];
    14 inline void gasse()
    15 {
    16     for(int i=1;i<=cnt;i++)
    17     {
    18         int p=i;
    19         for(int j=i+1;j<=cnt;j++)
    20             if(fabs(A[p][i])<fabs(A[j][i]))p=j;
    21         if(p!=i)
    22         for(int j=1;j<=cnt+1;j++)
    23             swap(A[i][j],A[p][j]);
    24         for(int j=i+1;j<=cnt;j++)
    25         {
    26             double tmp=A[j][i]/A[i][i];
    27             for(int k=i;k<=cnt+1;k++)
    28                 A[j][k]-=tmp*A[i][k];
    29         }
    30     }
    31     for(int i=cnt;i>=1;i--)
    32     {
    33         for(int j=i+1;j<=cnt;j++)
    34             A[i][cnt+1]-=A[j][cnt+1]*A[i][j];
    35         A[i][cnt+1]/=A[i][i];
    36     }
    37 }
    38 int main()
    39 {
    40     scanf("%d%d%d%d",&n,&m,&S,&T);
    41     for(int i=1;i<=m;i++)
    42     {
    43         int a,b;scanf("%d%d",&a,&b);
    44         add(a,b),add(b,a),du[a]++,du[b]++;
    45     }
    46     for(int i=1;i<=n;i++)
    47         scanf("%lf",&p[i]),k[i]=(1.0-p[i])/du[i];
    48     if(S==T)
    49     {
    50         for(int i=1;i<=n;i++)
    51             printf("%.10lf%c",i==S?1.0:0.0,i==n?'
    ':' ');
    52         return 0;
    53     }
    54     for(int i=1;i<=n;i++)
    55         for(int j=1;j<=n;j++)
    56             if(i!=j)
    57                 num[i][j]=++cnt;
    58     for(int t=1;t<=n;t++)
    59     {
    60         memset(f,0,sizeof(f));f[t]=1;
    61         for(int i=1;i<M;i++)
    62             for(int j=1;j<M;j++)
    63                 A[i][j]=0;
    64         for(int i=1;i<=n;i++)
    65             for(int j=1;j<=n;j++)
    66             {
    67                 if(i==j)continue;
    68                 int nu=num[i][j];
    69                 A[nu][nu]=1.0-p[i]*p[j];
    70                 for(int a=adj[i];a;a=s[a].next)
    71                 {
    72                     int u=s[a].zhong;
    73                     int nui=num[u][j];
    74                     if(u==j)A[nu][cnt+1]+=k[i]*p[j]*f[j];
    75                     else A[nu][nui]-=k[i]*p[j];
    76                 } 
    77                 for(int b=adj[j];b;b=s[b].next)
    78                 {
    79                     int v=s[b].zhong;
    80                     int nui=num[i][v];
    81                     if(i==v)A[nu][cnt+1]+=p[i]*k[j]*f[i];
    82                     else A[nu][nui]-=p[i]*k[j];
    83                 }
    84                 for(int a=adj[i];a;a=s[a].next)
    85                     for(int b=adj[j];b;b=s[b].next)
    86                     {
    87                         int u=s[a].zhong,v=s[b].zhong;
    88                         int nui=num[u][v];
    89                         if(u==v)A[nu][cnt+1]+=k[i]*k[j]*f[u];
    90                         else A[nu][nui]-=k[i]*k[j];
    91                     }
    92             }    
    93         gasse();
    94         ans[t]=A[num[S][T]][cnt+1];
    95     }
    96     printf("%.10lf",ans[1]);
    97     for(int i=2;i<=n;i++)
    98         printf(" %.10lf",ans[i]);
    99 } 
    codeforces113D
    Progress is not created by contented people.
  • 相关阅读:
    空心杯 电机
    scikit learn 安装
    python fromkeys() 创建字典
    python 清空列表
    mac最常用快捷键
    php while循环
    php 获取某个日期n天之后的日期
    php 添加时间戳
    php 格式化时间
    php 数值数组遍历
  • 原文地址:https://www.cnblogs.com/LadyLex/p/7000460.html
Copyright © 2011-2022 走看看