zoukankan      html  css  js  c++  java
  • BZOJ 3143 游走

    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

    题解

    若已知每条边期望走了多少次那么就可以贪心的求出解。
    (w_i) 表示第i条边期望走多少次。
    那么有(w_i = dp_u / d_u + dp_v / d_v)
    dp 是这个点期望走了多少次(走出!!)。
    (dp_i = display sum_{e(j , i)} dp_j / d_j)
    根据这个可以得到n个方程 , 用高斯消元消出答案即可。
    注意(a[1][n+1] = -1; dp[n][n] = 任意非0)

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<set>
    #include<map>
    using namespace std;
    const int N = 520 , M = N * N;
    inline int read()
    {
        register int x = 0 , f = 0; register char c = getchar();
        while(c < '0' || c > '9') f |= c == '-' , c = getchar();
        while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
        return f ? -x : x;
    }
    int n , m;
    int d[N] , eu[M] , ev[M];
    double a[N][N] , w[M] , x[N];
    
    void calc(int n , int m)
    {
    	for(int i = 1 ; i < n ; ++i)
    	{
    		int res = i;
    		for(int j = i + 1 ; j <= n ; ++j) if(fabs(a[j][i]) > fabs(a[res][i])) res = j;
    		if(i != res) swap(a[i] , a[res]);
    		for(int j = i + 1 ; j <= n ; ++j)
    		{
    			double k = a[j][i] / a[i][i];
    			for(int s = i ; s <= m ; ++s) a[j][s] -= a[i][s] * k;
    		}
    	}
    	for(int i = m-1 ; i >= 1 ; --i)
    	{
    		for(int j = i+1 ; j < m ; ++j) a[i][m] -= a[j][j] * a[i][j];
    		a[i][i] = a[i][m] / a[i][i];
    	}
    	for(int i = 1 ; i <= n ; ++i) x[i] = a[i][i];
    	return ;
    }
    
    int main()
    {
    	n = read(); m = read();
    	for(int i = 1 ; i <= m ; ++i) eu[i] = read() , ev[i] = read() , d[ev[i]]++ , d[eu[i]]++;
    	for(int i = 1 ; i <= m ; ++i)
    	{
    		a[eu[i]][ev[i]] += 1.0 / d[ev[i]];
    		a[ev[i]][eu[i]] += 1.0 / d[eu[i]];
    	}
    	for(int i = 1 ; i < n ; ++i) a[i][i] = -1 , a[n][i] = 0; a[n][n] = 1; a[1][n+1] = -1;
    	calc(n , n + 1);
    	for(int i = 1 ; i <= m ; ++i) w[i] = x[eu[i]] / d[eu[i]] + x[ev[i]] / d[ev[i]];
    	sort(w + 1 , w + 1 + m);
    	double ans = 0;
    	for(int i = 1 ; i <= m ; ++i) ans += i * w[m-i+1];
    	printf("%.3f
    " , ans);
    	return 0;
    }
    
  • 相关阅读:
    shiro标签
    ssm项目整合shiro
    关于POI读取模板的单元格位为null,或者无法正确获取样式的简单处理方案
    为什么wait的条件放在while里面,用if就不行
    Dto中有List<DTO> children,那么如何把List<Dto>转为List<VO>
    开发踩过的坑
    POI一直不能给sheet赋值
    写给研发的需求能不能不要废话
    写着写着就不知道自己定义的方法是干嘛的了
    一个if else的问题,卡了一个小时,我也是……
  • 原文地址:https://www.cnblogs.com/R-Q-R-Q/p/12334592.html
Copyright © 2011-2022 走看看