[HNOI2013]游走

题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:

3 3
2 3
1 2
1 3

输出样例#1:

3.333

说明

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

我们发现每条边对答案的贡献就是走这条边的期望(Σ次数*概率)*这条边的编号。

最优方案显然是求出所有期望之后大的期望对应小的编号。。。

但是怎么求边的期望呢???

边的期望直接求不好求,可以考虑从点的求得。

设E(x)为走x点的期望(Σ次数*概率),E(u,v)为走这条边的期望。

那么E(x,y)=E(x)/d(x)+E(y)/d(y),d(i)表示i点的度数。

当然如果x,y其中一个是n的话就不能算了,因为到了n就结束了,不可能再走这条边。

所以现在问题就变成了如何求每个点的期望。

显然E(n)=1,因为n是游戏的终点,最多也最少走一次。

对于其他的x,E(x)=ΣE(v)/d(v) ,条件是存在边(x,v)。

特殊的,对于E(1),右式还要+1,因为1是起点。

这是一个有后效性的方程,我们只能通过高斯消元求解。。。

(好像实数高斯消元的精度误差都很毒瘤,,,现在已经很迷茫eps到底取多少了hhhh)

#include<bits/stdc++.h>
#define ll long long
#define D long double
#define maxn 505
#define maxm 250005
using namespace std;
const D eps=10e-11;
D a[maxn][maxn],tot;
D ap[maxm],ans[maxn];
int n,m,u[maxm];
int v[maxm],d[maxn];
bool g[maxn][maxn];

inline int zt(D x){
    if(x>=-eps&&x<=eps) return 0;
    return x>0?1:-1;
}

inline void solve(){
    for(int i=1;i<n;i++){
    	int o=i;
    	for(int j=i+1;j<n;j++) if(zt(a[j][i]-a[o][i])==1) o=j;

    	if(o!=i)
    	    for(int k=i;k<=n;k++) swap(a[o][k],a[i][k]);

        for(int j=i+1;j<n;j++) if(zt(a[j][i])){
            D base=a[j][i]/a[i][i];
            for(int k=i;k<=n;k++) a[j][k]-=a[i][k]*base;
        }
    }

//	ans[n]=1.00;
    for(int i=n-1;i;i--){
        for(int j=n-1;j>i;j--) a[i][n]-=ans[j]*a[i][j];
        ans[i]=a[i][n]/a[i][i];
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",u+i,v+i);
        d[u[i]]++,d[v[i]]++;
        g[u[i]][v[i]]=g[v[i]][u[i]]=1;
    }

    for(int i=1;i<n;i++){
        a[i][i]=1.00;
        for(int j=1;j<n;j++) if(g[j][i]) a[i][j]=-1.00/(D)d[j];
    }
    a[1][n]=1.00;

    solve();

    for(int i=1;i<=m;i++) ap[i]=ans[u[i]]/d[u[i]]+ans[v[i]]/d[v[i]];
    sort(ap+1,ap+m+1);
    for(int i=1;i<=m;i++) tot+=ap[i]*(m-i+1.00);

    printf("%.3Lf\n",tot);
    return 0;
}

  

原文地址:https://www.cnblogs.com/JYYHH/p/8448087.html

时间: 2024-08-08 21:16:05

[HNOI2013]游走的相关文章

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 ---------------------------------------

【BZOJ3143】[Hnoi2013]游走 期望DP+高斯消元

[BZOJ3143][Hnoi2013]游走 Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小. Input 第一行是正整数N和M,分别表示该图的顶点数 和边数,接下来M行每行是整数u,v(1≤u,v

bzoj3143 [Hnoi2013]游走

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之间存在一条边. 输

[BZOJ 3143][Hnoi2013]游走(高斯消元+期望)

Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小. Solution 对于点u(u≠1):到达u的概率 f[u]=∑f[v]/d[v] (Edges(u,v)) 而f[1]=∑f[v]/d[v]+1

BZOJ3143 - HNOI2013游走【高斯消元】

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之间存在一条边. 输

BZOJ 3143 HNOI2013 游走 高斯消元 期望

这道题是我第一次使用高斯消元解决期望类的问题,首发A了,感觉爽爽的.... 中文题目,就不翻大意了,直接给原题: 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小. 输出最小的总分期望值. Solution: 这题贪心很明显

数学(概率):HNOI2013 游走

[题目描述] 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小. [输入格式] 第一行是正整数N和M,分别表示该图的顶点数 和边数,接下来M行每行是整数u,v(1≤u,v≤N),表示顶点u与顶点v之间存在一条边. 输入保证3

【BZOJ3143】[Hnoi2013]游走

一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小. 期望次数大的标号应该小 p[e] = p[e.x] / out[e.x] + p[e.y] / out[e.y] 剩下的和3270相同 #include <iostream

【BZOJ】3143: [Hnoi2013]游走 期望+高斯消元

[题意]给定n个点m条边的无向连通图,每条路径的代价是其编号大小,每个点等概率往周围走,要求给所有边编号,使得从1到n的期望总分最小(求该总分).n<=500. [算法]期望+高斯消元 [题解]显然,应使经过次数越多的边编号越小,问题转化为求每条边的期望经过次数. 边数太多,容易知道f(u,v)=f(u)/out(u)+f(v)/out(v),所以转化为求每个点的期望经过次数,这就是驱逐猪猡了. 设f[x]表示点x的期望经过次数,根据全期望公式(讨论"经过"的问题不能依赖于下一步