【LG3232】[HNOI2013]游走

题面

洛谷

题解

img

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (ch != '-' && (ch > '9' || ch < '0')) ch = getchar();
    if (ch == '-') w = -1 , ch = getchar();
    while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
    return w * data;
}
#define MAX_N 505 
struct Edge {
    int to, next; 
} e[MAX_N * MAX_N << 1];
int fir[MAX_N], cnt = 0;
void clearGraph() {
    memset(fir, -1, sizeof(fir));
    cnt = 0; 
}
void Add_Edge(int u, int v) {
    e[cnt].to = v, e[cnt].next = fir[u], fir[u] = cnt++; 
}
int N, M, d[MAX_N]; 
double A[MAX_N][MAX_N]; 
struct edg {
    int u, v;
    double P;
    bool operator < (const edg & rhs) const {
        return P < rhs.P; 
    } 
} ed[MAX_N * MAX_N]; 
int main () {
    clearGraph();
    N = gi(), M = gi();
    for (int i = 1; i <= M; i++) {
        int u = gi(), v = gi();
        Add_Edge(u, v);
        Add_Edge(v, u); 
        d[u]++, d[v]++;
        ed[i].u = u, ed[i].v = v; 
    }
    for (int i = 1; i <= N; i++) A[i][i] = 1.0; 
    for (int x = 1; x < N; x++) 
        for (int i = fir[x]; ~i; i = e[i].next) 
            if (e[i].to != N) A[x][e[i].to] -= 1.0 / d[e[i].to]; 
    A[1][N + 1] = 1; 
    for (int i = 1; i <= N; i++) { 
        int r = i; 
        for (int j = i + 1; j <= N; j++) 
            if (fabs(A[j][i]) > fabs(A[r][i])) r = j; 
        if (r != i)
            for (int j = 1; j <= N + 1; j++) swap(A[r][j], A[i][j]); 
        for (int j = i + 1; j <= N; j++) { 
            double f = A[j][i] / A[i][i]; 
            for (int k = i; k <= N + 1; k++) A[j][k] -= f * A[i][k]; 
        } 
    }
    for (int i = N; i >= 1; i--) {
        for (int j = i + 1; j <= N; j++)
            A[i][N + 1] -= A[j][N + 1] * A[i][j];
        A[i][N + 1] /= A[i][i]; 
    }
    for (int i = 1; i <= M; i++) {
        int u = ed[i].u, v = ed[i].v;
        ed[i].P = 1.0 * A[u][N + 1] / d[u] + 1.0 * A[v][N + 1] / d[v]; 
    }
    
    sort(&ed[1], &ed[M + 1]);
    double ans = 0;
    for (int i = 1; i <= M; i++) ans += ed[i].P * (M - i + 1.0);
    printf("%0.3lf\n", ans); 
    return 0; 
}

猜你喜欢

转载自www.cnblogs.com/heyujun/p/10405064.html