BZOJ 3143 游走 高斯消元

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3143

中文题目。
F(v) 表示小Z在图上游走时,在v点走的次数
这样就可以根据图上的链接关系 构造出N个方程在求解既可

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 500 + 5;
const double eps = 1e-4;
typedef double Matrix[maxn][maxn];
Matrix A;
bool adj[maxn][maxn];
int n,m,ous[maxn];
struct edge{
    int u,v;
    double p;
    bool operator<(edge o)const{
        return p > o.p;
    }
}edges[maxn * maxn];
void INIT(){
    memset(adj,0,sizeof adj);
    memset(ous,0,sizeof ous);
    memset(A,0,sizeof A);
}
void Gauss(){
    int i,j,k,p;
    for(i = 0;i < n;++i){
        k = i;
        for(p = i + 1;p < n;++p) if( fabs(A[p][i]) > fabs(A[k][i]) ) k = p;
        if(k != i) for(p = 0;p <= n;++p) swap(A[i][p],A[k][p]);
        for(k = i + 1;k < n;++k){
            double tmp = A[k][i] / A[i][i];
            for(p = i;p <= n;++p) A[k][p] = A[k][p] - tmp * A[i][p];
        }
    }
    for(j = n - 1;j >= 0;--j){
        double tmp = 0;
        for(k = j + 1;k < n;++k) tmp += A[j][k] * A[k][n];
        A[j][n] = (A[j][n] - tmp) / A[j][j];
    }
}

int main(){
    INIT();
    scanf("%d%d", &n,&m);
    for(int i = 0;i < m;++i){
        scanf("%d%d",&edges[i].u,&edges[i].v);
        edges[i].v--,edges[i].u--;
        ous[edges[i].u]++;
        ous[edges[i].v]++;
        adj[edges[i].u][edges[i].v] = adj[edges[i].v][edges[i].u] = 1;
    }
    n--;
    //构造方程
    for(int i = 0;i < n;++i){
        for(int j = 0;j < n;++j){
            if(adj[j][i]){
                A[i][j] = 1.0 / ous[j];
            }
        }
        A[i][i] -= 1.0;
    }
    A[0][n] = -1.0;

    //高斯消元
    Gauss();
    for(int i = 0;i < m;++i){
        int v = edges[i].v,u = edges[i].u;
        edges[i].p = A[v][n] / ous[v] + A[u][n] / ous[u];
    }
    sort(edges,edges + m);
    double ans = 0;
    for(int i = 0;i < m;++i){
        ans += edges[i].p * (i + 1);
    }
    printf("%.3f\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值