bzoj3143 游走 概率 高斯消元

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3143

题目大意是说:给出一张无向图,找出一种加权值的方式,使得从1到n期望带权路径长度最短,输出最短路长度。

首先,根据基本常识,走的次数多的边,权值越小越好(废话)。

于是问题转变为:找出每条边的期望经过次数。

设i边期望经过次数为f[i],则f[i]就为两个端点期望经过次数与走到这条边概率之商的和(没看懂?就是f[i]=x[duan1]/du[duan1]+x[duan2]/du[duan2],x[i]表示i点期望经过次数,du[i]表示i点在图中的度)。

问题进一步转化为:找出每个点的期望经历次数。

首先,由于我们走过终点就可以不走了,所以我们忽略掉n节点。

根据期望的线性性可以得出x[i]=sigma{(x[j]+1)/du[j]}。

把每个点的情况都弄出来,就会发现这是一个有n个变量,n个式子的线性方程组。

于是用死也打不对的高斯消元解决。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 const int maxn=505,maxm=500005;
 8 const double eps=1e-7;
 9 struct node
10 {
11     int from,to,next;
12 }edge[maxm];
13 int head[maxn],tot;
14 void addedge(int u,int v)
15 {
16     edge[++tot]=(node){u,v,head[u]};head[u]=tot;
17 }
18 int du[maxn],n,m;
19 double a[maxn][maxn],x[maxn],f[maxm];
20 void Gauss()
21 {
22     int im,num=1;
23     for(int k=1;k<=n;k++,num++)
24     {
25         im=k;
26         for(int i=k+1;i<=n;i++)
27             if(fabs(a[i][k])>fabs(a[im][k]))im=i;
28         if(im!=k)
29             for(int i=k;i<=n+1;i++)swap(a[num][i],a[im][i]);
30         if(fabs(a[num][k])==0)
31         {
32             num--;
33             continue;
34         }
35         for(int i=num+1;i<=n;i++)
36         {
37             if(!a[num][i])continue;
38             double t=a[i][k]/a[num][k];
39             for(int j=k;j<=n+1;j++)
40                 a[i][j]-=t*a[k][j];
41         }
42     }
43     for(int i=n;i>=1;i--)
44     {
45         for(int j=n;j>=i+1;j--)
46             a[i][n+1]-=x[j]*a[i][j];
47         x[i]=a[i][n+1]/a[i][i];
48     }
49 }
50 bool cmp(double a,double b)
51 {
52     return a>b;
53 }
54 int haha()
55 {
56     //freopen("walk.in","r",stdin);
57     //freopen("walk.out","w",stdout);
58     scanf("%d%d",&n,&m);
59     for(int i=1;i<=m;i++)
60     {
61         int a,b;scanf("%d%d",&a,&b);
62         du[a]++;du[b]++;
63         addedge(a,b);addedge(b,a);
64     }
65     a[1][n--]=-1;
66     for(int i=1;i<=n;i++)
67     {
68         a[i][i]=-1;
69         for(int j=head[i];j;j=edge[j].next)
70         {
71             int v=edge[j].to;
72             if(v!=n+1)
73                 a[i][v]+=(double)1/(du[v]);
74         }
75     }
76     Gauss();
77     for(int i=1;i<=tot;i++)
78         f[(i-1)>>1]+=x[edge[i].to]/du[edge[i].to];
79     sort(f,f+m,cmp);
80     double ans=0;
81     for(int i=0;i<m;i++)ans+=f[i]*(i+1);
82     printf("%0.3lf\n",ans);
83 }
84 int sb=haha();
85 int main(){;}
时间: 2024-10-06 21:09:44

bzoj3143 游走 概率 高斯消元的相关文章

[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

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

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

bzoj 3143 [Hnoi2013]游走【高斯消元+dp】

参考:http://blog.csdn.net/vmurder/article/details/44542575 和2337有点像 设点u的经过期望(还是概率啊我也分不清,以下都分不清)为\( x[u] \) ,度为 \( in[u] \),边\( (u,v) \) 的经过期望为 \( \frac{x[u]}{in[u]}+\frac{x[v]}{in[v]} \) 那么转换为求每个点的经过期望,\( x[u]=\sum_{v}^{v\subset son(u)}\frac{x[v]}{in[v

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

如果纯模拟,就会死循环,而随着循环每个点的期望会逼近一个值,高斯消元就通过列方正组求出这个值. #include<cstdio> #include<cctype> #include<cstring> #include<algorithm> using namespace std; const double eps=1e-9; bool vis[503]; double f[503],a[503][503],ans[500*500]; int N,M,cnt=

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 游走(高斯消元)

题意:一个无向连通图,顶点从1编号到n,边从1编号到m.小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达n号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这m条边进行编号,使得小Z获得的总分的期望值最小. 思路:显然,需要求出每条边的期望经过次数,然后排序贪心赋值即可,但是每条边的期望经过次数是什么呢? 是 E(e)=E(u)/D(u) + E(v)/D(v) (u,v∈e

UVA 10828 - Back to Kernighan-Ritchie(概率+高斯消元)

UVA 10828 - Back to Kernighan-Ritchie 题目链接 题意:给图一个流程图,有结点的流程,每次进入下一个流程概率是均等的,有q次询问,求出每次询问结点的执行期望 思路:高斯消元,每个结点的期望等于所有前趋结点的期望/出度的和,由于存在无限循环的情况,不能直接递推,利用高斯消元去做,判断无解的情况既为无限循环,注意如果一个式自xi为0,但是xn也为0,xi值应该是0,表示无法到达 代码: #include <cstdio> #include <cstring

BZOJ 3143 HNOI2013 游走 高斯消元 期望

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

【BZOJ-3143】游走 高斯消元 + 概率期望

3143: [Hnoi2013]游走 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2264  Solved: 987[Submit][Status][Discuss] Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数