题解 P3232 [HNOI2013]游走
洛谷P3232[NOI2013]游走
题目描述
给定一个 n 个点 m 条边的无向连通图,顶点从 1 编号到 n,边从 1 编号到 m。
小 Z 在该图上进行随机游走,初始时小 Z 在 1 号顶点,每一步小 Z 以相等的概率随机选择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数。当小 Z 到达 n 号顶点时游走结束,总分为所有获得的分数之和。 现在,请你对这 m 条边进行编号,使得小 Z 获得的总分的期望值最小。
输入格式
第一行是两个整数,分别表示该图的顶点数 n 和边数 m。
接下来 m 行每行两个整数 u,v表示顶点 u 与顶点 v 之间存在一条边。
输出格式
输出一行一个实数表示答案,保留三位小数。
输入输出样例
输入
3 3
2 3
1 2
1 3
输出
3.333
说明提示
边 (1,2)编号为 1,边(1,3) 编号2,边(2,3) 编号为 3。
题解
正解的做法应该是期望dp+高斯消元QAQ
第一次接触到这样的题,我也是鼓捣了好半天
要想总体的期望值最小,就必须让经过次数越多的边的编号越小
那么这道题的主要部分就是搞每条边的期望经过次数
问题来了,边的期望并不好求,但是点的好求!!
用du[i]为点i的出度或入度,num[i]表示i点的期望经过值,f(u,v)为期望经过值
\(f(u,v)=\frac{num[u]} {du[u]}+\frac{num[v]} {du[v]}\)
求一个点的期望经过值就要用到高斯消元了
设s[i][j]为第i个方程第j项的系数
每个点经过自己的系数定为1;
\(s[i][i]=1\)
如果某个点与i相连接那么他的系数就是-1/该点的出度
\(s[i][j]=-\frac{1}{du[j]}\)
其他的系数就是0了
特殊的对于n而言,经过他就不会在出去,所以第n个方程处第n项外其余系数均为0
点1与点n一定会被经过,所以只有这两个式子的值是1,其余均为0,为了方便计算,我们把第i个式子的值存到s[i][n+1]上。
$s[i][n+1]= \sum_{j=1}^n x_j*s[i][j] $
最后在排个序就OK了
Code
#include<bits/stdc++.h>//万能头
#define ll long long
using namespace std;
const int M=125e3;
int n,m,sum,tot,head[2*M+5],ver[2*M+5],nxt[2*M+5],fro[2*M+5];
double du[505],s[505][505],num[505],ans;
priority_queue<double> q;//利用优先队列排序
void add(int u,int v)//邻接表存边
{
ver[++tot]=v;
fro[tot]=u;
nxt[tot]=head[u];
head[u]=tot;
}
void init()//初始化
{
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
du[u]++; du[v]++;
}
}
void gauss()//高斯消元
{
for(int i=1;i<=n;i++)//正推
{
int pos=0;
for(int j=1;j<=n;j++)
if(s[i][j])
{
pos=j;
break;
}
if(s[i][pos]!=1&&s[i][pos])
for(int j=n+1;j>=pos;j--)
s[i][j]/=s[i][pos];
for(int j=i+1;j<=n;j++)
{
if(!s[j][pos])
continue;
for(int k=n+1;k>=pos;k--)
s[j][k]-=s[i][k]*s[j][pos];
}
}
for(int i=n;i>=2;i--)//逆推
{
int pos=0;
for(int j=1;j<=n;j++)
if(s[i][j])
{
pos=j;
break;
}
if(s[i][pos]!=1&&s[i][pos])
for(int j=n+1;j>=pos;j--)
s[i][j]/=s[i][pos];
for(int j=1;j<i;j++)
{
if(!s[j][pos])
continue;
for(int k=n+1;k>=pos;k--)
s[j][k]-=s[i][k]*s[j][pos];
}
}
}
int main()
{
init();//初始化
for(int i=1;i<=n;i++)
for(int j=head[i];j;j=nxt[j])
{
int from=ver[j];
if(from!=n)//因为n不可能出来,所以第i个xn系数一定为0
s[i][from]=-1/du[from];
}
for(int i=1;i<=n;i++)
s[i][i]=1;
for(int i=1;i<n;i++)
s[n][i]=0;
s[n][n+1]=s[1][n+1]=1;
gauss();//高斯消元
for(int i=1;i<=n;i++)//记录xi的值
for(int j=1;j<=n;j++)
if(s[i][j]==1)
{
num[j]=s[i][n+1];
break;
}
for(int i=1;i<tot;i+=2)//计算每条边的期望经过值
{
int x=fro[i],y=ver[i];
q.push(num[x]/du[x]*(x!=n)+num[y]/du[y]*(y!=n));
}
while(!q.empty())//优先队列排序
{
sum++;
ans+=sum*q.top();
q.pop();
}
printf("%.3lf",ans);
return 0;
}
第一次用LaTeX,不熟练,望包涵orz
题解 P3232 [HNOI2013]游走的更多相关文章
- P3232 [HNOI2013]游走 解题报告
P3232 [HNOI2013]游走 题目描述 一个无向连通图,顶点从\(1\)编号到\(N\),边从\(1\)编号到\(M\). 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概 ...
- P3232 [HNOI2013]游走——无向连通图&&高斯消元
题意 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编 ...
- 洛谷P3232[HNOI2013]游走
有一个无向简单连通图,顶点从 \(1\) 编号到 \(n\),边从 \(1\) 编号到 \(m\) 小Z在该图上进行随机游走,初始时小Z在\(1\)号顶点,每一步小Z以相等的概率随机选 择当前顶点的某 ...
- [bzoj3143] [洛谷P3232] [HNOI2013] 游走
Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点, ...
- P3232 [HNOI2013]游走
吐槽 傻了傻了,对着题解改了好长时间最后发现是自己忘了调用高斯消元了... 思路 期望题,分配编号,显然编号大的分给贡献次数小的,所以需要知道每个边被经过次数的期望 然后边被经过的次数的期望就是连接的 ...
- BZOJ 3143 Luogu P3232 [HNOI2013]游走 (DP、高斯消元)
题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3143 (luogu) https://www.luogu.org/pro ...
- 洛谷 P3232 [HNOI2013]游走
链接: P3232 题意: 和上次考试 T4 的简化且无修改一样,经典图上高斯消元求期望. 分析: 要求出每个点的期望出发次数 \(f_i\),每个点度数为 \(d_i\),有 \[f1=\sum\d ...
- 洛谷P3232 [HNOI2013]游走(高斯消元+期望)
传送门 所以说我讨厌数学……期望不会高斯消元也不会……好不容易抄好了高斯消元板子被精度卡成琪露诺了…… 首先,我们先算出走每一条边的期望次数,那么为了最小化期望,就让大的期望次数乘上小编号 边的期望次 ...
- 【BZOJ3143】[Hnoi2013]游走 期望DP+高斯消元
[BZOJ3143][Hnoi2013]游走 Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 ...
随机推荐
- 消息队列RabbitMQ(五):死信队列与延迟队列
死信队列 引言 死信队列,英文缩写:DLX .Dead Letter Exchange(死信交换机),其实应该叫做死信交换机才更恰当. 当消息成为Dead message后,可以被重新发送到另一个交换 ...
- pass在if中
pass在if中是停止if成立后的操作. 如 num=1 while num<=100: if num==50: pass #当作先占位 elif num>=60 and n ...
- Spring 注解动态数据源设计实践
Spring 动态数据源 动态数据源是什么?解决了什么问题? 在实际的开发中,同一个项目中使用多个数据源是很常见的场景.比如,一个读写分离的项目存在主数据源与读数据源. 所谓动态数据源,就是通过Spr ...
- 使用 Yarn workspace,TypeScript,esbuild,React 和 Express 构建 K8S 云原生应用(一)
本文将指导您使用 K8S ,Docker,Yarn workspace ,TypeScript,esbuild,Express 和 React 来设置构建一个基本的云原生 Web 应用程序. 在本教程 ...
- [c++] 二级指针的原理
示例 将值(实参)传递给值(形参),无法更改val 1 #include <iostream> 2 using namespace std; 3 4 void change(int mem ...
- [Qt]《开发指南》3.1源码分析
界面: ButterflyGraph: 可以看出,本工程在主程序main里调用窗口界面qmywidget,窗口界面继承了QWidget,并调用自定义类qperson,推测是qmywidget类中的一个 ...
- grub救援模式
http://www.jinbuguo.com/linux/grub.cfg.html
- 053.Python前端Django框架模板层
模板层 一 模板语法之变量 在 Django 模板中遍历复杂数据结构的关键是句点字符, 语法: {{ var_name }} [root@node10 mysite]# cat app01/urls. ...
- MyBatis 动态 SQL 语句中出现 '<' 的问题
问题描述 映射接口方法如下: /** * 根据姓名和年龄查询用户信息 * @param name 姓名 * @param user 获取年龄 * @return */ public List<U ...
- linux 进程信号集合 sigset_t -(转自linengeir的专栏)
sigset_t 号集及信号集操作函数:信号集被定义为一种数据类型: typedef struct { unsigned long sig[_NSIG_WORDS]: } sigset_t 信号集用来 ...