BZOJ3143: [Hnoi2013]游走(期望DP 高斯消元)
时间:2022-05-07
本文章向大家介绍BZOJ3143: [Hnoi2013]游走(期望DP 高斯消元),主要内容包括Input、Output、Sample Input、Sample Output、HINT、Source、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
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
3 3 2 3 1 2 1 3
Sample Output
3.333
HINT
边(1,2)编号为1,边(1,3)编号2,边(2,3)编号为3。
Source
这题真TM恶心啊。。
思路大概是先表示出边的概率,然后表示出点的概率
发现点的概率不能直接搞
然后高斯消元搞一搞
最后贪心的加边,显然概率越小的编号应该越大
详细一点的题解在这里
https://www.luogu.org/problemnew/solution/P3232
#include<cstdio>
#include<cstring>
#include<algorithm>
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2)?EOF:*p1++)
using namespace std;
const int MAXN=1e6+10;
const double eps=1e-7;
char buf[1<<23],*p1=buf,*p2=buf;
inline int read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int N,M;
struct node
{
int u,v,nxt;
}edge[MAXN];
int head[MAXN],num=1;
inline void AddEdge(int x,int y)
{
edge[num].u=x;
edge[num].v=y;
edge[num].nxt=head[x];
head[x]=num++;
}
double f[1001][1001],ans[MAXN],E[MAXN],inder[MAXN];
int S[MAXN],T[MAXN];
int dcmp(double x)
{
if(x<eps&&x>-eps) return 0;
else return x<0?-1:1;
}
void Gauss()
{
for(int i=1;i<N;i++)
{
int mx=i;
for(int j=i+1;j<N;j++)
if( dcmp(f[j][i]-f[mx][i])>0 ) mx=j;
if(mx!=i) swap(f[i],f[mx]);
for(int j=i+1;j<N;j++)
{
double tmp=f[j][i]/f[i][i];
for(int k=i;k<=N;k++)
f[j][k]-=(double)tmp*f[i][k];
}
}
for(int i=N-1;i>=1;i--)
{
for(int j=i+1;j<N;j++)
f[i][N]-=ans[j]*f[i][j];
ans[i]=f[i][N]/f[i][i];
}
}
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#else
#endif
memset(head,-1,sizeof(head));
N=read(),M=read();
for(int i=1;i<=M;i++)
{
int x=read(),y=read();
AddEdge(x,y);AddEdge(y,x);
inder[x]++;inder[y]++;
S[i]=x;T[i]=y;
}
f[1][N]=1;
for(int i=1;i<N;i++) f[i][i]=1;
for(int i=1;i<N;i++)
for(int j=head[i];j!=-1;j=edge[j].nxt)
if(edge[j].v!=N)
f[i][edge[j].v]=(double)-1.00/inder[edge[j].v];
Gauss();
for(int i=1;i<=M;i++)
E[i]=ans[S[i]]/inder[S[i]]+ans[T[i]]/inder[T[i]];
sort(E+1,E+M+1);
double out=0;
for(int i=1;i<=M;i++)
out+=E[i]*(M-i+1);
printf("%.3lf",out);
return 0;
}
- Python标准库(1) — itertools模块
- C++从键盘输入文件结束符
- java cpu高达100%问题 排查
- (43) 剖析TreeMap / 计算机程序的思维逻辑
- Spring Cloud第一篇 Eureka简介及原理
- 华为面试题——约瑟夫问题的C++简单实现(循环链表)
- (49) 剖析LinkedHashMap / 计算机程序的思维逻辑
- Python多进程并行编程实践-mpi4py的使用
- 华为面试题——一道关于指针方面的编程题(C/C++)
- Spring Cloud第二篇 创建一个Eureka Server
- 数据挖掘实战(一):Kaggle竞赛经典案例剖析
- 华为面试题——单向链表倒转(一次遍历)
- Flask一步步搭建web应用
- (44) 剖析TreeSet / 计算机程序的思维逻辑
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用bat执行java项目
- Core + Vue 后台管理基础框架2——认证
- Core + Vue 后台管理基础框架3——后端授权
- Core + Vue 后台管理基础框架4——前端授权
- ent orm笔记4---Code Generation
- Core + Vue 后台管理基础框架5——系统审计
- Core + Vue 后台管理基础框架6——业务日志
- Lucene笔记一
- android9.0中SharedPreferences源码分析(一)
- Core + Vue 后台管理基础框架8——Swagger文档
- .net core国际化
- Cache-Aside Pattern
- Lucene笔记二
- Spring的事务传播行为
- Kubernetes架构简介