3143: [Hnoi2013]游走
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3171 Solved: 1390
[ 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
Sample Output
无向连通图
只要知道每条边经过的期望,就可以排序贪心了
而对于边e(u, v),经过这条边的期望为:经过u点的期望/u点度数+经过v点的期望/v点度数
所以这题还是求经过每个点次数的期望
设经过第i个点的期望次数为x[i],第i个点度数为in[i],那么有方程组
x[i] = ∑(x[j]/in[j]) (存在边e(i, j), j!=n)
但是1号点和n号点特殊,一开始就在1号点所以
x[1]-1 = ∑(x[j]/in[j]) (存在边e(1, j), j!=n)
而到了n号点就结束了所以
1-x[n] = ∑(x[j]/in[j]) (存在边e(n, j), j!=n),这也是为什么所有的方程都要j!=n
这样就可以列出n个n元方程,高斯消元求解即可
最后求出边期望贪心
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
typedef struct Road
{
int x, y;
double q;
bool operator < (const Road &b) const
{
if(q<b.q)
return 1;
return 0;
}
}Road;
Road s[250005];
double Jz[505][505], c[505], in[505];
void Gauss(int n, int m)
{
int i, j, p, q, r;
p = q = 1;
while(p<=n && q<=m)
{
r = p;
for(i=p+1;i<=n;i++)
{
if(fabs(Jz[i][q])>fabs(Jz[r][q]))
r = i;
}
/*if(fabs(Jz[r][q])<eps)
return 0; ----方程无解*/
for(i=q;i<=m;i++)
swap(Jz[r][i], Jz[p][i]);
swap(c[r], c[p]);
c[p] /= Jz[p][q];
for(i=q+1;i<=m;i++)
Jz[p][i] /= Jz[p][q];
for(i=1;i<=n;i++)
{
if(Jz[i][q] && i!=p)
{
for(j=q+1;j<=m;j++)
Jz[i][j] -= Jz[p][j]*Jz[i][q];
c[i] -= c[p]*Jz[i][q];
Jz[i][q] = 0;
}
}
q++, p++;
}
//return 1;
}
int main(void)
{
int n, m, i;
double ans;
scanf("%d%d", &n, &m);
for(i=1;i<=m;i++)
{
scanf("%d%d", &s[i].x, &s[i].y);
in[s[i].x]++, in[s[i].y]++;
}
c[1] = -1, c[n] = 1;
for(i=1;i<=n-1;i++)
Jz[i][i] = -1;
for(i=1;i<=m;i++)
{
Jz[s[i].x][s[i].y] += 1/in[s[i].y];
Jz[s[i].y][s[i].x] += 1/in[s[i].x];
}
for(i=1;i<=n-1;i++)
Jz[i][n] = 0;
Jz[n][n] = 1;
Gauss(n, n);
for(i=1;i<=m;i++)
s[i].q = c[s[i].x]/in[s[i].x]+c[s[i].y]/in[s[i].y];
sort(s+1, s+m+1);
ans = 0;
for(i=1;i<=m;i++)
ans += (m-i+1)*s[i].q;
printf("%.3f\n", ans);
return 0;
}