[USACO Hol10] 臭气弹 图上期望概率dp 高斯

记住一开始和后来的经过是两个事件因此概率可以大于一

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<vector>
#include<algorithm>
#define MAXN 333
using namespace std;
typedef double D;
D a[MAXN][MAXN],ans[MAXN];
int p,q,n,m;
vector<int> Link[MAXN];
int in[MAXN];
inline D abs(D x)
{
   return x<0?0.0-x:x;
}
inline void swap(D &x,D &y)
{
   D temp=x;
   x=y;
   y=temp;
}
void gauss()
{ 
   for(int i=1,k=1;i<=n;i++,k++)
   {
     int t=i;
     D h=abs(a[i][k]);
     for(int j=i+1;j<=n;j++)
      if(abs(a[j][k])>abs(a[t][k]))
      {
        t=j;
        h=abs(a[j][k]);
      }
     if(t!=i)
     {
       for(int j=k;j<=n+1;j++)
         swap(a[i][j],a[t][k]);
     }
     for(int j=i+1;j<=n;j++)
     {
        h=a[j][k]/a[i][k];
        for(int l=k;l<=n+1;l++)
         a[j][l]-=a[i][l]*h;
     }
   }
   for(int i=n;i>0;i--)
   {
     for(int j=i+1;j<=n;j++)
      a[i][n+1]-=ans[j]*a[i][j];
     ans[i]=a[i][n+1]/a[i][i];
   }
}
int main()
{
    freopen("dotp.in","r",stdin);
    freopen("dotp.out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&p,&q);
    for(int i=1;i<=m;i++)
    {
      int x,y;
      scanf("%d%d",&x,&y);
      Link[x].push_back(y);
      in[x]++;
      Link[y].push_back(x);
      in[y]++;
    }
    for(int i=1;i<=n;i++)
    {
      a[i][i]=-1.0;
      for(int j=0;j<Link[i].size();j++)
        a[i][Link[i][j]]=(D)(1.0-(D)p/q)*(1.0/in[Link[i][j]]);
      a[i][1+n]=0.0;
    }
    a[1][1+n]=-1.0;
    gauss();
    for(int i=1;i<=n;i++)
    {
      ans[i]=ans[i]*p/q;
      if(ans[i]==-0.0)
       ans[i]=0.0;
      printf("%.9lf\n",ans[i]);
    }
    return 0;
}

 

posted @ 2017-06-24 11:02  TS_Hugh  阅读(354)  评论(0编辑  收藏  举报