hnoi2013游走 (高斯消元)

题意:给一个无向图,给边附上1~M的权值,使得1到N的期望得分最小。

显然应该让期望经过次数最多的边的权值尽量小。但是由于这是个无向图,肯定有环,可以无限制走,不是很好确定概率。事实上可以发现虽然可以无限走,但是走到每个点的概率之间是相互制约的,也就是可以列一些方程出来,设f[i]为i走到节点的概率,则f[i]=Σf[j]/du[j],其中j到i右边,du表示每个点的度。然后由于是从1开始的,1的期望一开始设置为1。然后用高斯约当强行解这个方程即可。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
const int inf = 0x3f3f3f3f;
#define DB double
const int MAXN = 505;
int n, m;

DB a[MAXN][MAXN];
void gaoss(int n)
{
	int col = 1, row = 1;
    for (; col <= n; ++col, ++row)
	{
        int maxr = row;
		rep(i, row+1, n)
            if (fabs(a[i][col]) > fabs(a[maxr][col]))
				maxr = i;
        if (maxr != row) rep(i, col, n+1) swap(a[maxr][i],a[row][i]);
		rep(i, row+1, n+1) a[row][i] /= a[row][col];
        a[row][col] = 1;
		rep(i, 1, n)
            if (i != row) {
				rep(j, col+1, n+1)
                    a[i][j] -= a[i][col]*a[row][j];
                a[i][col] = 0;
            }
    }
}

int ui[MAXN*MAXN], vi[MAXN*MAXN];
int du[MAXN];
DB f[MAXN*MAXN], ans;

int main()
{
	cin >> n >> m;
	rep(i, 1, m)
	{
		cin >> ui[i] >> vi[i];
		++du[ui[i]], ++du[vi[i]];
	}
	rep(i, 1, m)
	{
		a[ui[i]][vi[i]] = -1.0 / du[vi[i]];
		a[vi[i]][ui[i]] = -1.0 / du[ui[i]];
	}
	rep(i, 1, n-1) a[i][i] = 1, a[i][n] = 0;
	a[n][n] = 0, a[1][n] = 1;
	gaoss(n-1);
	rep(i, 1, m)
		f[i] = a[ui[i]][n]/du[ui[i]]+a[vi[i]][n]/du[vi[i]];
	sort(f+1, f+m+1);
	rep(i, 1, m) ans += f[i] * (m-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、付费专栏及课程。

余额充值