题解-CSA Round#18 Randomly Permuted Costs
Problem
题意概要:给定一个有重边有自环 \(n\) 点 \(m\) 边的有向无环图(DAG),每条边有其权值,每当你走到一个点 \(x\) 时,所有从 \(x\) 连出去的边上的权值会互相随机打乱,问从 \(S\) 到 \(T\) 最短路长度的期望
\(n,m\leq 10^3\)
Solution
首先第一步很明显是按照 DAG 的拓扑序一个个地转移,只需考虑处理每个点怎么转移,设 \(f[x]\) 表示从 \(x\) 走到 \(T\) 的最短路长度期望
先暂不考虑重边和自环
设当前在点 \(x\),且共有 \(K\) 条出边,那么 \(f[x]\) 应该会有 \(K^2\) 种取值(\(K\) 种出边边权和 \(K\) 个 \(f[v](x\rightarrow v)\) 值自由搭配)
考虑计算若当前选择了 边权 \(w\) 与 出点\(f[v](x\rightarrow v)\) 搭配,需要计算 \(w+f[v]\) 作为所有 \(K\) 种搭配下最小的权值的概率
对于 \(x\) 的每一个不同于 \(v\) 的出点 \(t\),需要计算出有多少边权与其搭配使得这组搭配花费总和不小于 \(w\) 与 \(v\) 的这组搭配,记作 \(ret[t]\)
一个结论是 \(ret[t]\) 与 \(f[t]\) 正相关(因为若 \(f[t]\) 越大,则给边权 \(t_w\) 的限制越小,\(f[t]+t_w\geq w+f[v]\Leftrightarrow t_w\geq w+f[v]-f[t]\))。而对于 \(f[i]\leq f[j]\),定有 \(ret[i] \leq ret[j]\),且两者集合之间为包含关系(后者包含前者)
则考虑将所有出点按照 \(f\) 值从小至大排序后,\(t\) 处在第 \(i\) 位,则减去其包含的区间,这一位能选的配对有 \(ret[t]-(i-1)\) 种
所以边权 \(w\) 与出点 \(f[v]\) 的配对为 \(K\) 个配对最小的情况,有 \(\prod_t (ret[t]-i+1)\) 种,这样就能在 \(O(K^3)\) 的时间内计算出每个点的 \(f\) 值;事实上,按照配对的权值排序,计算增量出现的概率,每一次只会改变两个值,可以 \(O(1)\) 解决,算上排序,可以在 \(O(K^2\log K)\) 的时间内计算出每个点的 \(f\) 值
考虑上重边,发现 \(x\) 若有 \(k\) 条边指向 \(v\),则只要假定 \(x\) 有 \(k\) 个 \(f\) 值为 \(f[v]\) 的出点即可
考虑上自环,可以使用二分 \(f\) 的方式,每次假定 \(f=mid\),和由此算出来的 \(f'\) 进行对比,若 \(f<f'\) 则代表 \(mid\) 设得比较小,反之则越大(事实上二分中也可以用一点点小优化,若 \(f<f'\) 则将 \(l\) 设为 \(f'\) 而非 \(mid\),这样实际上算一种小迭代?速度上升一倍)
加上二分后就需要将对配对的排序提到外头来,内层仅处理自环的部分后线性归并一下,否则复杂度会变成两个 \(\log\)
时间复杂度为 \(O(n\log p+m^2\log m)\) (\(p\) 视精度要求而定)
Code
#include <bits/stdc++.h>
using namespace std;
#define For(x,y) for(int x=1;x<=y;++x)
const double eps = 1e-8;
const int N = 1010;
struct Edge {int v, nxt; double w;} a[N+N];
int head[N], Head[N], _;
int deg[N], q[N];
double f[N];
int n, m, S, T;
inline void ad() {
static int x, y; static double w; scanf("%d%d%lf",&x,&y,&w);
a[++_].v = y, a[_].w = w, a[_].nxt = head[x], head[x] = _;
a[++_].v = x, a[_].nxt = Head[y], Head[y] = _;
if(x != y) ++deg[x];
}
typedef pair<double,int> pr;
pr brr[N*N], arr[N*N], crr[N*N];
int arc, brc, crc;
double ew[N*N]; int _ew;
double ot[N*N]; int _ot;
int ret[N], self_circle;
void init(int x) {
arc = _ew = _ot = self_circle = 0;
for(int i=head[x];i;i=a[i].nxt) {
ew[++_ew] = a[i].w;
if(a[i].v == x) ++self_circle;
else ot[++_ot] = f[a[i].v];
}
sort(ew + 1, ew + _ew + 1);
sort(ot + 1, ot + _ot + 1);
For(i, _ew) For(j, _ot)
arr[++arc] = make_pair(ew[i] + ot[j], j);
sort(arr + 1, arr + arc + 1);
}
double calc(int x, double sw) {
f[x] = sw, brc = 0;
int t = 0; while(t < _ot and ot[t+1] < sw) ++t;
For(i, _ew) For(j, self_circle)
brr[++brc] = make_pair(ew[i] + sw, t + j);
For(i, arc) if(arr[i].second > t) arr[i].second += self_circle;
merge(arr+1, arr+arc+1, brr+1, brr+brc+1, crr+1);
For(i, arc) if(arr[i].second > t) arr[i].second -= self_circle;
crc = arc + brc;
For(i, _ew) ret[i] = _ew;
double coe = 1, ans = 0;
for(int i=1, id; i <= crc and coe > eps; ++i) {
ans += coe * (crr[i].first - crr[i-1].first);
id = crr[i].second;
coe /= ret[id] - (id - 1);
--ret[id];
coe *= ret[id] - (id - 1);
}
return ans;
}
void solve(int x) {
init(x);
if(!_ot) return f[x] = 1e9, void();
double l = calc(x, 0), r = calc(x, 1e7), mid, res;
while(l + eps < r) {
mid = 0.5 * (l + r);
res = calc(x, mid);
if(res > mid) l = res;
else r = res;
}
f[x] = l;
}
int main() {
scanf("%d%d%d%d",&n,&m,&S,&T);
while(m--) ad();
int he = 1, ta = 0;
For(i, n) {
if(!deg[i]) q[++ta] = i;
f[i] = 1e9;
}
while(he <= ta) {
int x = q[he++];
for(int i=Head[x];i;i=a[i].nxt)
if(!(--deg[a[i].v]))
q[++ta] = a[i].v;
if(x == T) f[x] = 0;
else solve(x);
}
if(f[S] < 1e8) printf("%.7lf\n",f[S]);
else puts("-1");
return 0;
}
题解-CSA Round#18 Randomly Permuted Costs的更多相关文章
- CSA Round #54 $\ $Voting
CSA Round #54 \(\ \)Voting 题目大意: 原题网址:戳我戳我! 一次歌唱比赛中,一位歌手刚刚结束表演,评委正在打分. 一共有 \(n\) 位评委,他们每人可以打 \(1\) 分 ...
- Codeforces Beta Round #18 (Div. 2 Only)
Codeforces Beta Round #18 (Div. 2 Only) http://codeforces.com/contest/18 A 暴力 #include<bits/stdc+ ...
- “玲珑杯”ACM比赛 Round #18
“玲珑杯”ACM比赛 Round #18 Start Time:2017-07-15 12:00:00 End Time:2017-07-15 15:46:00 A -- 计算几何你瞎暴力 Time ...
- 题解-CSA Beta Round#1 Number Elimination
Problem CSA-Beta Round#3 题意概要:给定 \(n\) 个数组成的序列,定义一次操作: 在当前序列中选择两个数,将其中较小的数从序列中删除(若两个数相同,则删除在序列中更靠前的) ...
- 喵哈哈村的魔法考试 Round #18 (Div.2) 题解
喵哈哈村的古怪石碑(一) 题解:暴力check一下是等比数列还是等差数列,然后输出答案即可.注意如果数据范围是1e9的话,就要快速幂了. 代码: #include <cstdio> #in ...
- Codeforces Beta Round #18 (Div. 2 Only) C. Stripe 前缀和
C. Stripe Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/problem/18/C ...
- [题解] Codeforces Round #549 (Div. 2) B. Nirvana
Codeforces Round #549 (Div. 2) B. Nirvana [题目描述] B. Nirvana time limit per test1 second memory limit ...
- 竞赛题解 - CF Round #524 Div.2
CF Round #524 Div.2 - 竞赛题解 不容易CF有一场下午的比赛,开心的和一个神犇一起报了名 被虐爆--前两题水过去,第三题卡了好久,第四题毫无头绪QwQ Codeforces 传送门 ...
- [题解]Codeforces Round #709 (Div. 1, based on Technocup 2021 Final Round) - A. Basic Diplomacy
[题目] A. Basic Diplomacy [描述] Aleksey有n个朋友,有一个m天的假期,每天都需要一个朋友来陪他.给出每天有空的朋友的编号,要求同一个朋友来的天数不能超过m/2上取整.求 ...
随机推荐
- vuejs2从入门到精通视频教程
https://www.cnblogs.com/web-666/p/8648607.html 一.基础部分 0.课件 1.介绍 2.vue实例 3.模板语法 4.计算属性和观察者 5.Class与St ...
- Win10 设备管理器一个USB设备描述符请求失败解决方法
问题:进入设备管理器,发现[通用串行总线控制器]下有一项带有黄色[!]未知USB设备(设备描述符请求失败). 或者 解决方法如下: 1.点击Windows键 +R或者(点击系统桌面左下角[开始],在开 ...
- Java 8 新特性总结
一.Java 8 Lambda表达式 Lambda表达式,也称为闭包,它是推动Java 8发布的最重要新特性. Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法). 1.1 语法 使用 ...
- 宝塔 ssl https无法访问使用
https 使用的是443端口 请确保 云上的与宝塔上的443端口开放即可
- 解决“Jquery的each里面return失效的问题”
参考文章:http://blog.csdn.net/coffeesmile/article/details/53349860 问题描述: 集中获取页面的一些元素,然后用each循环处理这些元素,如果其 ...
- 转「服务器运维」如何解决服务器I/O过高的问题
问题缘起: 当我习惯性地用top查看任务运行状态时,发现我运行的100个任务,只有3个在运行,其他都在摸鱼状态.同时发现我的任务进程都是"D"状态(未截图),而不是R(运行)状态. ...
- WPF richTextBox 滚动到某项
在网上没有找到合适的代码,自己写了一段,还有待优化... 直接上代码 /// <summary> /// 滚动到某项 /// </summary> /// <param ...
- 基于EasyDSS流媒体解决方案创建视频点播、短视频、视频资源库等视频播放系统
随着前端技术的不断发展,视频点播早已不再是IE6时代的浏览器嵌入式Windows Media Player.也不是后来的flash media player需要的rtmp点播流,现在能够唯一满足全终端 ...
- 【k8s node断电重启】
kubernetes断电重启 导致部分pod无法删除 dashboard上处于黄色 kubectl get处于terminate 状态 kubectl delete报错: An error occur ...
- CSS控制元素背景透明度总结
方法一:CSS3的background rgba filter:progid:DXImageTransform.Microsoft.gradient(enabled='true',startColor ...