Problem

CSA Round 18

题意概要:给定一个有重边有自环 \(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的更多相关文章

  1. CSA Round #54 $\ $Voting

    CSA Round #54 \(\ \)Voting 题目大意: 原题网址:戳我戳我! 一次歌唱比赛中,一位歌手刚刚结束表演,评委正在打分. 一共有 \(n\) 位评委,他们每人可以打 \(1\) 分 ...

  2. Codeforces Beta Round #18 (Div. 2 Only)

    Codeforces Beta Round #18 (Div. 2 Only) http://codeforces.com/contest/18 A 暴力 #include<bits/stdc+ ...

  3. “玲珑杯”ACM比赛 Round #18

    “玲珑杯”ACM比赛 Round #18 Start Time:2017-07-15 12:00:00 End Time:2017-07-15 15:46:00 A -- 计算几何你瞎暴力 Time ...

  4. 题解-CSA Beta Round#1 Number Elimination

    Problem CSA-Beta Round#3 题意概要:给定 \(n\) 个数组成的序列,定义一次操作: 在当前序列中选择两个数,将其中较小的数从序列中删除(若两个数相同,则删除在序列中更靠前的) ...

  5. 喵哈哈村的魔法考试 Round #18 (Div.2) 题解

    喵哈哈村的古怪石碑(一) 题解:暴力check一下是等比数列还是等差数列,然后输出答案即可.注意如果数据范围是1e9的话,就要快速幂了. 代码: #include <cstdio> #in ...

  6. 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 ...

  7. [题解] Codeforces Round #549 (Div. 2) B. Nirvana

    Codeforces Round #549 (Div. 2) B. Nirvana [题目描述] B. Nirvana time limit per test1 second memory limit ...

  8. 竞赛题解 - CF Round #524 Div.2

    CF Round #524 Div.2 - 竞赛题解 不容易CF有一场下午的比赛,开心的和一个神犇一起报了名 被虐爆--前两题水过去,第三题卡了好久,第四题毫无头绪QwQ Codeforces 传送门 ...

  9. [题解]Codeforces Round #709 (Div. 1, based on Technocup 2021 Final Round) - A. Basic Diplomacy

    [题目] A. Basic Diplomacy [描述] Aleksey有n个朋友,有一个m天的假期,每天都需要一个朋友来陪他.给出每天有空的朋友的编号,要求同一个朋友来的天数不能超过m/2上取整.求 ...

随机推荐

  1. c语言程序课程设计题目

    <C语言程序设计>课程设计课题表 一.A类 .职工信息管理系统设计 职工信息包括职工号.姓名.性别.年龄.学历.工资.住址.电话等(职工号不重复).试设计一职工信息管理系统,使之能提供以下 ...

  2. [String]两个右补空格使字符串达到固定长度的函数 来自网上 请君自取

    代码: package fixsizestring; public class TestClass { public static void main(String[] args) { for(int ...

  3. nginx中的超时配置

    nginx.conf配置文件中timeout超时时间设置 client_header_timeout 语法 client_header_timeout time默认值 60s上下文 http serv ...

  4. Docs-.NET-C#-指南-语言参考-关键字-值类型:内置数值转换

    ylbtech-Docs-.NET-C#-指南-语言参考-关键字-值类型:内置数值转换 1.返回顶部 1. 内置数值转换(C# 参考) 2019/10/22 C# 提供了一组整型和浮点数值类型. 任何 ...

  5. centos6的kibana7.1无法启动报错 FATAL Error: /lib64/libc.so.6: version `GLIBC_2.14' not found 升级glibc的问题处理

    centos6的kibana7.1无法启动报错 FATAL  Error: /lib64/libc.so.6: version `GLIBC_2.14' not found 升级glibc的问题处理 ...

  6. Access与SQL中的IsNull(),IS NULL的区别

    Access也有IsNull函数,但意义和参数却和T-SQL中的不同. 在T-SQL(也就是SQL Server所支持的SQL语言)中,IsNull的作用是把空值替代成指定的值.然而在Access中, ...

  7. layui时间控件闪退的问题

    项目上线,发现后台管理系统layui的子页面出现时间控件闪退的问题,根本选取不到时间. 其原因是:如果出现页面找到多个节点,只有第一个节点能正常使用后面的节点都会闪退,可以理解为目前laydate不支 ...

  8. iframe子页面无法返回上一页的问题

    本文讨论的场景是ipad终端. 如题,因业务需要,需要使用iframe嵌套子页面.让外层始终保持一个socket连接,避免socket每跳转一个页面都要重新关闭建立连接的问题.但是这样问题来了,上线后 ...

  9. 多个wav音频文件合并(连接)成一个文件

    场景:一段声音从浏览器麦克风缓冲上一段一段发给服务器,按照时间戳生成很多文件. 目的:把他们按时间顺序连到一个时间轴上. 命令如下: ffmpeg -f concat -i list.txt out. ...

  10. AD 常用策略

    配置WSUS 配置NTPS 配置用户配置文件漫游 配置漫游区磁盘配额 配置修改本地管理员用户名 配置修改本地管理员密码 配置网络验证(提示是否联网错误) 配置允许开设永久共享 配置允许开设共享打印机 ...