题意与分析

定义走到每条边的期望为\(e_i\),一开始的想法是给定一个\(\large\sum_{i=1}^n e_i a_i\),求一个a的排列使得这个和最小。问题在于这样等于没对题目作分析,而且题目的难度没有被转化降低。于是(在高人指点下)我们想到,如果先求出\(e_i\),然后按照从小到大的顺序贪心的编号,问题就直接转化成求走到每个边的期望。

边的期望是一个新操作,但是其实不难:定义走到点的期望是\(f_i\),考虑一条边\((u, v)\),对于这条边而言,只有从u和从v才能走到这条边,那么它的期望就是\(\large e_i=\frac{f_u}{degree_u}+\frac{f_v}{degree_v}\)。于是问题又转化成走到各个点的期望。

如果这是个DAG,那么问题是一个dp(\(dp[j]\)表示从j到n的期望长度,\(dp[i] = \sum_{i\to j} \frac{dp[j]+1}{degree_i}\),具体问题见BZOJ-3036)。问题是这题并不是,场面有点尴尬。但是上面DAG的方程加起来共有n个,而我们要求n-1个解,这提示了我们用高斯消元解决这个问题。用高斯消元的话我们就把公式变形一下:

\[e_i = \sum_{j=1}^n p_{i,j}e_{j} , 2\le i \le n
\]

其中\(p_{i,j}\)表示从j走到i的概率,对于第一个点该式子的右边还要加上一个1(因为一开始就在这个点上了,不妨思考下平凡的情况)。这样一来就可以用高斯消元解决这一题了。

问题的逐步转化是这一题的关键。

代码

#include <bits/stdc++.h>

using namespace std;

vector<pair<int, int>> edges;
vector<int> G[505]; double arr[505][505];
int main() {
int n, m;
while (cin >> n >> m) {
for (int i = 1, u, v; i <= m; ++i) {
cin >> u >> v;
if (u > v)
swap(v, u);
edges.push_back(make_pair(u, v));
G[u].push_back(v);
G[v].push_back(u);
}
memset(arr, 0, sizeof(arr));
for (int i = 1; i <= n; ++i)
arr[i][i] = -1.0;
arr[1][n + 1] = -1.0;
for (int i = 1; i < n; i++) {
for (int j = 0; j < G[i].size(); ++j)
arr[G[i][j]][i] += 1.0 / (int)G[i].size();
}
for (int i = 1; i <= n; ++i) {
int idx = i;
for (int j = i + 1; j <= n; ++j)
if (fabs(arr[j][i]) > fabs(arr[idx][i]))
idx = j;
assert(fabs(arr[idx][i]) > 1e-10);
if (idx != i)
for (int j = i; j <= n + 1; ++j)
swap(arr[i][j], arr[idx][j]);
for (int j = 1; j <= n; ++j)
if (i != j) {
double t = arr[j][i] / arr[i][i];
for (int k = i; k <= n + 1; ++k)
arr[j][k] -= arr[i][k] * t;
}
}
/*
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n + 1; ++j) {
cout << arr[i][j] << " ";
}
cout << endl;
}
*/
double e_node[505];
double e_edge[500 * 500 / 2 + 5];
memset(e_edge, 0, sizeof(e_edge));
memset(e_node, 0, sizeof(e_node));
for (int i = 1; i <= n; ++i) {
e_node[i] = arr[i][n + 1] / arr[i][i];
}
for (int i = 0; i < edges.size(); ++i) {
e_edge[i] += e_node[edges[i].first] / G[edges[i].first].size();
if (edges[i].second != n)
e_edge[i] += e_node[edges[i].second] / G[edges[i].second].size();
}
sort(e_edge, e_edge + m);
double ans = 0;
for (int i = 0; i < m; ++i)
ans += e_edge[i] * (m - i);
cout << fixed << setprecision(3) << ans << endl;
}
return 0;
}

「专题训练」游走(BZOJ-3143)的更多相关文章

  1. 游走 bzoj 3143

    游走(2s 128MB)walk [问题描述] [输入格式] [输出格式] [样例输入] 3 3 2 3 1 2 1 3 [样例输出] 3.333 [样例说明] 题解: 主要算法:贪心:高斯消元: 题 ...

  2. 「HNOI 2013」游走

    题目链接 戳我 \(Solution\) 首先申明几个变量: f[x]:到点x的概率, vis[x]:x点的度 dp[x][y]:(x,y)这条边的概率 number[x][y]:x这条边的编号 下面 ...

  3. 「专题训练」k-Tree(CodeForces Round #247 Div.2 C)

    题意与分析(Codeforces-431C) 题意是这样的:给出K-Tree--一个无限增长的树,它的每个结点都恰有\(K\)个孩子,每个节点到它\(K\)个孩子的\(K\)条边的权重各为\(1,2, ...

  4. 「专题训练」Air Raid(HDU-1151)

    题目 在一个城市里有\(n\)个地点和\(k\)条道路,道路是无环的(也就是说一定可以二分染色--回路长度为偶数0),现在伞兵需要去n个地点视察,只能沿着路的方向走,问最少需要多少伞兵. 分析 这是什 ...

  5. 「专题训练」Machine Schedule(HDU-1150)

    题意 在一个工厂,有两台机器\(A, B\)生产产品.\(A\)机器有\(n\)种工作模式(模式\(0\),模式\(1\)--模式\(n-1\)).\(B\)机器有\(m\)种工作模式(模式\(0\) ...

  6. 「专题训练」Collecting Bugs(POJ-2096)

    题意与分析 题意大致是这样的:给定一个\(n\times s\)的矩阵,每次可以随机的在这个矩阵内给一个格子染色(染过色的仍然可能被选中),问每一行和每一列都有格子被染色的次数的期望. 这题如果从概率 ...

  7. 「专题训练」Hard problem(Codeforces Round #367 Div. 2 C)

    题意与分析 题意:给出\(n\)个字符串,可以反转任意串,反转每个串都有其对应的花费\(c_i\).经过操作后是否能满足字符串\(\forall i \in [1,n] \text{且} i \in ...

  8. 「专题训练」Boredom(CodeForces Round #260 Div.1 A)

    题意(Codeforces-455A) 给你\(n\)个数,你每次可以选择删除去一个数\(x\)获得\(x\)分,但是所有为\(x+1\)和\(x-1\)的数都得删去.问最大获得分数. 分析 这是一条 ...

  9. 「HNOI2013」游走

    「HNOI2013」游走 题目描述 一个无向连通图,顶点从 \(1\) 编号到 \(N\) ,边从 \(1\) 编号到 \(M\) .小 \(Z\) 在该图上进行随机游走,初始时小 \(Z\) 在 \ ...

随机推荐

  1. 终于明白为什么要赋值给ret ,

    def my_max(a,b): if a > b: return a else: return b my_max(10,45)# 如果只是这样,那么只是运行了并产生返回值,但没有打印返回值t ...

  2. ES6中map和set用法

    ES6中map和set用法 --转载自廖雪峰的官方网站 一.map Map是一组键值对的结构,具有极快的查找速度. 举个例子,假设要根据同学的名字查找对应的成绩,如果用Array实现,需要两个Arra ...

  3. 【转载】uWSGI配置翻译

    英文原版: http://uwsgi-docs.readthedocs.io/en/latest/Options.html 转载地址: http://www.cnblogs.com/zhouej/ar ...

  4. 前端统计利器:Sentry & Matomo

    今天主要说下两款前端统计工具的使用,Sentry & Matomo.以下主要是统计代码接入方式,因此使用前提是你已经在自己的服务器上搭建好了Sentry和Matomo的服务器 Sentry统计 ...

  5. Array.prototype.reduce 的理解与实现

    Array.prototype.reduce 是 JavaScript 中比较实用的一个函数,但是很多人都没有使用过它,因为 reduce 能做的事情其实 forEach 或者 map 函数也能做,而 ...

  6. jQuery实现滚动时动态加载页面内容

    有些网站的网页内容不是一次性加载完毕的,而是在鼠标向下滚动时动态加载的,这是怎么做到的呢?看下面代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ...

  7. Java并发编程--7.Java内存操作总结

    主内存和工作内存 工作规则 Java内存模型, 定义变量的访问规则, 即将共享变量存储到内存和取出内存的底层细节  所有的变量都存储在主内存中,每条线程有自己的工作内存,工作内存中用到的变量, 是从主 ...

  8. Day9 JSP

    JSP概述 JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术.JSP实际上就是Servlet. jsp = html + ...

  9. 【Agile123】Automated Test in Agile

    https://www.infoq.com/articles/thoughts-on-test-automation-in-agile Start Small Balance the cost vs. ...

  10. ethers.js-4-Contracts

    Contracts A Contract is an abstraction of an executable program on the Ethereum Blockchain. A Contra ...