【Luogu】P3232游走(高斯消元解概率)

  题目链接

  参见远航之曲dalao的题解,我再写一遍的话就没啥意思了。

  

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cstdlib>
#include<cmath>
#define maxn 505
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

double s[maxn][maxn];

double indl[maxn];

struct Edge{
    int next,to;
}edge[maxn*maxn];
int head[maxn],num;
inline void add(int from,int to){
    edge[++num]=(Edge){head[from],to};
    head[from]=num;
}

struct Node{
    int from,to;double p;
    bool operator <(const Node &a)const{    return p<a.p;    }
}q[maxn*maxn];

double ans[maxn];

int main(){
    int n=read(),m=read();
    for(int i=1;i<=m;++i){
        int x=read(),y=read();
        indl[x]++;    indl[y]++;
        add(x,y);
        add(y,x);
        q[i]=(Node){x,y,0};
    }
    for(int i=1;i<n;++i){
        s[i][i]=1;
        for(int j=head[i];j;j=edge[j].next){
            int to=edge[j].to;
            if(to!=n)    s[i][to]=-1/indl[to];
        }
    } 
    s[1][n]=1;
    for(int i=1;i<n;++i){
        int now=i;
        for(int j=i+1;j<n;++j)
            if(fabs(s[now][i])<fabs(s[j][i]))    now=j;
        if(now^i)    swap(s[now],s[i]);
        double ret=s[i][i];
        for(int j=i;j<=n;++j)    s[i][j]/=ret;
        for(int j=i+1;j<n;++j){
            ret=s[j][i];
            for(int k=1;k<=n;++k)    s[j][k]-=ret*s[i][k];
        }
    }
    
    ans[n-1]=s[n-1][n];
    for(int i=n-2;i;--i){
        ans[i]=s[i][n];
        for(int j=i+1;j<n;++j)    ans[i]-=ans[j]*s[i][j];
    }
    
    for(int i=1;i<=m;++i)    q[i].p=ans[q[i].from]/indl[q[i].from]+ans[q[i].to]/indl[q[i].to];
    sort(q+1,q+m+1);
    double fin=0;
    for(int i=1;i<=m;++i)    fin+=q[i].p*(m-i+1);
    printf("%.3lf",fin);
    return 0;
}

 

posted @ 2018-04-12 08:56  Konoset  阅读(200)  评论(0编辑  收藏  举报