您的位置:首页 > 其它

hnoi2013游走 (高斯消元)

2016-01-18 13:16 357 查看
题意:给一个无向图,给边附上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]
= 0;
a

= 0, a[1]
= 1;
gaoss(n-1);
rep(i, 1, m)
f[i] = a[ui[i]]
/du[ui[i]]+a[vi[i]]
/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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: