bzoj3143 游走 期望dp+高斯消元
题意:
一个无向连通图,顶点从1编号到N,边从1编号到M。
小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数。当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和。
现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小。
思路:很显然,我们肯定希望经过次数最多的边的标号最小,但是由于边的数量可能很多,而且好像也不存在什么很好转移的东西,那么我们就需要考虑点。
假设E[X]代表从x这个点出发的次数,那么对于{u,v}这样一条边的被经过的次数显然等于$\frac{E[u]}{deg[u]}+\frac{E[v]}{deg[v]}$ deg代表度数,也就是从其他点过来的概率。所以我们只要算出E[x]就可以完成这道题了。
我们考虑一般的u(除了起点和终点),显然易得$E[X]=\sum \frac {E[v]}{deg[v]}$。
而终点就是的E[X]就是0,起点的期望,除了上述的式子,还需要加入最初始的1.(游戏开局),由于我们这样可以得到n个式子,而且n个式子之间存在推来推去的关系,显然可以考虑高斯消元。
所以就按照上面这个式子高斯消元求解,然后把边按经过次数排序就是答案了。
#pragma GCC optimize (2)
#pragma G++ optimize (2)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,b,a) for(int i=b;i>=a;i--)
#define clr(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pii pair<int,int >
using namespace std;
typedef long long ll;
ll rd()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int maxn=;
const int inf=0x3f3f3f3f;
int T,n,m;
vector<int >ve[maxn];
struct edge{
int u,v;
double g;
friend bool operator<(const edge &a,const edge &b){
return a.g>b.g;
}
}e[maxn*maxn];
const double eps=1e-;
int equ=,var=;
double a[maxn][maxn],x[maxn],deg[maxn];
int Gauss()//高斯消元 返回 0 无解 返回 1有解
{
int i,j,k,col,max_r;
for(k=,col=;k<equ&&col<var;k++,col++)
{
max_r=k;
for(i=k+;i<equ;i++)
if(fabs(a[max_r][col])>fabs(a[max_r][col]))
max_r=i;
if(fabs(a[max_r][col])<eps) return ;
if(k!=max_r)
{
for(j=col;j<var;j++)
swap(a[k][j],a[max_r][j]);
swap(x[k],x[max_r]);
}
x[k]/=a[k][col];
for(j=col+;j<var;j++) a[k][j]/=a[k][col];
a[k][col]=;
for(i=;i<equ;i++)
{
if(i!=k)
{
x[i]-=x[k]*a[i][col];
for(j=col+;j<var;j++) a[i][j]-=a[k][j]*a[i][col];
a[i][col]=;
}
}
}
return ;
}
int main(){
cin>>n>>m;
rep(i,,m){
scanf("%d%d",&e[i].u,&e[i].v);
deg[e[i].u]++;
deg[e[i].v]++;
ve[e[i].u].push_back(e[i].v);
ve[e[i].v].push_back(e[i].u);
}
x[]=;
a[n-][n-]=;
equ=var=n+;
rep(i,,n-){
a[i-][i-]=;
//for(auto &v:ve[i]){
for(int j=;j<ve[i].size();j++){ int v=ve[i][j];
if(v!=n)
a[i-][v-]=-/deg[v];
}
}
Gauss();
for(int i=;i<=m;i++){
e[i].g=;
if(e[i].u!=n)
e[i].g+=x[e[i].u-]/deg[e[i].u];
if(e[i].v!=n)
e[i].g+=x[e[i].v-]/deg[e[i].v];
}
sort(e+,e++m);
double ans=;
rep(i,,m){
ans+=i*e[i].g;
}
printf("%.3f\n",ans);
}
bzoj3143 游走 期望dp+高斯消元的更多相关文章
- 【BZOJ3143】[Hnoi2013]游走 期望DP+高斯消元
[BZOJ3143][Hnoi2013]游走 Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 ...
- BZOJ3143: [Hnoi2013]游走(期望DP 高斯消元)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3597 Solved: 1618[Submit][Status][Discuss] Descript ...
- bzoj 3143 [Hnoi2013]游走 期望dp+高斯消元
[Hnoi2013]游走 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3394 Solved: 1493[Submit][Status][Disc ...
- 2018.09.23 bzoj3143: [Hnoi2013]游走(dp+高斯消元)
传送门 显然只需要求出所有边被经过的期望次数,然后贪心把边权小的边定城大的编号. 所以如何求出所有边被经过的期望次数? 显然这只跟边连接的两个点有关. 于是我们只需要求出两个点被经过的期望次数. 对于 ...
- BZOJ 3143: [Hnoi2013]游走 [概率DP 高斯消元]
一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分 ...
- BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元
BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元 题意: 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机 ...
- bzoj3143: [Hnoi2013]游走(贪心+高斯消元)
考虑让总期望最小,那么就是期望经过次数越多的边贪心地给它越小的编号. 怎么求每条边的期望经过次数呢?边不大好算,我们考虑计算每个点的期望经过次数f[x],那么一条边的期望经过次数就是f[x]/d[x] ...
- 期望dp+高斯消元——bzoj3143
比较经典的题,题解看网上的..https://www.cnblogs.com/GXZlegend/p/7054536.html 自己sort弄错了..还以为是高斯消元写歪了.. #include< ...
- 【noi2019集训题1】 脑部进食 期望dp+高斯消元
题目大意:有n个点,m条有向边,每条边上有一个小写字母. 有一个人从1号点开始在这个图上随机游走,游走过程中他会按顺序记录下走过的边上的字符. 如果在某个时刻,他记录下的字符串中,存在一个子序列和S2 ...
随机推荐
- 【java】自定义排序
使用Comparable接口 这里定义了一个类Node,有两个属性,id,age. 排序方法是,先根据id升序排,id一样,age降序排. 里面有一个compareTo方法.返回值有三个 1. < ...
- Neo4J(Cypher语句)初识
欢迎各路大神临幸寒舍 以下节点标签为people,friend,用户自己也可以设置成其他标签,查询时需要用到标签.这个标签可以类比为关系数据库中的表名 创建节点.关系 创建节点(小明):create ...
- 案例-2D会旋转的盒子(rotate), 会缩放的盒子(scale),动画(animation)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- ubuntu14.04 配置android studio环境
二.复制所需的文件到ubuntu 2.1.如果你还没有linux版本的android studio.sdk.jdk请先下载所需文件,我已经上传到百度网盘了 下载地址: android studio-l ...
- windows如何在当前路径下快速打开cmd
直接在打开的文件夹地址栏当中输入cmd即可.
- 【Jquery】this和event.target的区别
1.js中事件是会冒泡的,所以this是可以变化的,但event.target不会变化,它永远是直接接受事件的目标DOM元素: 2.this和event.target都是dom对象,如果要使用jque ...
- Splay(区间翻转)&树套树(Splay+线段树,90分)
study from: https://tiger0132.blog.luogu.org/slay-notes P3369 [模板]普通平衡树 #include <cstdio> #inc ...
- Python:验证码识别
说明:此验证方法很弱,几乎无法识别出正确的验证码
- javascript表单验证的例子
function checkUsername(){ //对username的内容进行验证. //要求:首字符是字母或下划线,其他由下划线字母数字组成,共4-20位 var inputOb=docume ...
- 包管理工具(npm、yarn)
npm包管理工具 1. npm的包安装分为本地安装(local).全局安装(global)两种,从敲的命令行来看,差别只是有没有-g而已. 2. 这两种安装方式的区别: 本地安装(安装在命令行运行所在 ...