zoukankan      html  css  js  c++  java
  • BZOJ 3143: [Hnoi2013]游走( 高斯消元 )

    我一开始的想法是设f(x)表示点x到N路径的期望长度, 那么f(u) = (∑f(v)+w(u,v)) / degreeu, f(N)=0, 我们代入入消元应该可以得到f(1)关于各条边长的关系式f(1)=∑we..然后贪心, 按照他们的系数来给边权...但是不会实现..但是我感觉是可行的..PoPoQQQ题解:http://blog.csdn.net/PoPoQQQ/article/details/42234607

    -----------------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
     
    using namespace std;
     
    typedef pair<int, int> pii;
    typedef long double ld;
     
    const int maxn = 509;
     
    ld mat[maxn][maxn], p[1000000];
    int deg[maxn], N, M;
    pii Eg[1000000];
     
    struct edge {
    int to;
    edge* next;
    } E[maxn * maxn], *pt = E, *head[maxn];
     
    void AddEdge(int u, int v) {
    deg[pt->to = v]++; pt->next = head[u]; head[u] = pt++;
    }
     
    void Init() {
    memset(deg, 0, sizeof deg);
    scanf("%d%d", &N, &M); N--;
    for(int i = 0; i < M; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    Eg[i] = make_pair(--u, --v);
    AddEdge(u, v);
    AddEdge(v, u);
    }
    }
     
    void Work() {
    for(int i = 0; i < N; i++) {
    int r = i;
    for(int j = i; ++j < N; )
    if(fabs(mat[j][i]) > fabs(mat[r][i])) r = j;
    if(r != i) {
    for(int j = 0; j <= N; j++)
    swap(mat[r][j], mat[i][j]);
    }
    for(int j = i; ++j < N; ) {
    ld t = mat[j][i] / mat[i][i];
    for(int k = i; k <= N; k++)
    mat[j][k] -= mat[i][k] * t;
    }
    }
    for(int i = N; i--; ) {
    for(int j = i; ++j < N; )
    mat[i][N] -= mat[i][j] * mat[j][N];
    mat[i][N] /= mat[i][i];
    }
    }
     
    bool Cmp(const ld &i, const ld &j) {
    return i > j;
    }
     
    int main() {
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
    Init();
    memset(mat, 0, sizeof mat);
    mat[0][N]--;
    for(int i = 0; i < N; i++) {
    for(edge* e = head[i]; e; e = e->next)
    if(e->to != N) mat[i][e->to] += ld(1) / deg[e->to];
    mat[i][i]--;
    }
    Work();
    memset(p, 0, sizeof p);
    for(int i = 0; i < M; i++) {
    pii &t = Eg[i];
    p[i] = mat[t.first][N] / deg[t.first] + mat[t.second][N] / deg[t.second];
    }
    sort(p, p + M, Cmp);
    ld ans = 0;
    for(int i = 0; i < M; i++)
    ans += p[i] * (i + 1);
    printf("%.3lf ", (double) ans);
    return 0;
    }

    ----------------------------------------------------------------------- 

    3143: [Hnoi2013]游走

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1526  Solved: 660
    [Submit][Status][Discuss]

    Description

    一个无向连通图,顶点从1编号到N,边从1编号到M。 
    小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数。当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和。 
    现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小。

    Input

    第一行是正整数N和M,分别表示该图的顶点数 和边数,接下来M行每行是整数u,v(1≤u,v≤N),表示顶点u与顶点v之间存在一条边。 输入保证30%的数据满足N≤10,100%的数据满足2≤N≤500且是一个无向简单连通图。

    Output

    仅包含一个实数,表示最小的期望值,保留3位小数。

    Sample Input

    3 3
    2 3
    1 2
    1 3

    Sample Output

    3.333

    HINT

    (1,2)编号为1,边(1,3)编号2,边(2,3)编号为3

    Source

  • 相关阅读:
    The 4 Most Important Skills for a Software Developer
    Youth is not a time of life, it is a state of mind——青春不是一段年华,而是一种心境
    英雄所见略同——每个人都有的一套价值体系观念
    28法则————10分钟休息胜过半小时努力
    离职员工心声
    员工必备素质、能力——职场精英
    安卓sqlite数据库的使用
    安卓adb命令的使用
    windows使用命令行,提高效率
    命令行编译java文件(含第三方jar包)
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/5017611.html
Copyright © 2011-2022 走看看