题目链接

2019.9.2更新


第二天睡醒想了想发现好像搜一遍就可以过,赛时写的花里胡哨的还错了,太菜了QAQ

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + ;
struct node {
int s, e, next;
}edge[maxn];
int head[maxn], len;
void init() {
memset(head, -, sizeof(head));
len = ;
}
void add(int s, int e) {
edge[len].s = s;
edge[len].e = e;
edge[len].next = head[s];
head[s] = len++;
}
double dp[maxn], dp2[maxn];
int vis[maxn],n;
void dfs(int x) {
if (vis[x])
return;
vis[x] = ;
dp[x] = dp2[x] = ;
if (x == n)
return;
int num = ;
for (int i = head[x]; i != -; i = edge[i].next) {
int y = edge[i].e;
dfs(y);
dp[x] += dp[y];
dp2[x] += dp2[y];
num++;
}
dp[x] += num + , dp[x] /= num;
dp2[x] += (num + )*dp[x], dp2[x] /= num;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
int m, x, y;
init();
scanf("%d%d", &n, &m);
for (int i = ; i <= m; i++)
scanf("%d%d", &x, &y), add(x, y);
memset(vis, , sizeof(vis));
dfs();
printf("%.2f\n", dp2[]);
}
}

原文


绝望ing!!!

搞了3个小时的D,到最后也没过,吃饭的时候突然想到错了,改一改就过了Orz.

遗憾!!错在求了拓扑序,要用a[n]->a[1],结果用成了n->1。要被队友骂死了QAQ

而且样例刚好1-n是拓扑序(


题意是说,在DAG中从1到n,每次有x/(x+1)的概率到相连的点,1/(x+1)的概率原地不动,(x为相连的点的个数)。每次移动需要一天,每次移动会消耗当前天数数值那么多的能量,求到达n点的期望能量消耗。

一开始就蛮有感觉的,DAG上跑期望dp,先跑期望天数,再跑期望能量,设dp[i]为i点到n点的期望天数,则初始dp[n]=0,转移为$dp[i]=\tfrac{1}{x+1}*\sum dp[j]+\tfrac{1}{x+1}*dp[i]+1$ i->j有边。

然后再跑期望能量,dp2[i]为i到n点的期望能量,初始为dp2[n]=0,转移为$dp2[i]=\tfrac{1}{x+1}*\sum dp2[j]+\tfrac{1}{x+1}*dp2[i]+dp[i]$ i->j有边。

代码极度丑陋,望见谅。

 #include <bits/stdc++.h>
using namespace std;
const int maxn = 4e5 + ;
struct node {
int s, e, next;
}edge[maxn], edge2[maxn];
int head[maxn], head2[maxn], len, len2;
void init() {
memset(head, -, sizeof(head));
memset(head2, -, sizeof(head2));
len = len2 = ;
}
void add(int s, int e) {
edge[len].s = s;
edge[len].e = e;
edge[len].next = head[s];
head[s] = len++;
}
void add2(int s, int e) {
edge2[len2].s = s;
edge2[len2].e = e;
edge2[len2].next = head2[s];
head2[s] = len2++;
}
double dp[maxn], dp2[maxn];
int in[maxn], a[maxn], num[maxn];
void solve(int n) {
int lens = ;
queue<int>q;
for (int i = ; i <= n; i++)
if (in[i] == ) q.push(i);
while (!q.empty()) {
int p = q.front(); q.pop();
a[++lens] = p;
for (int i = head[p]; i != -; i = edge[i].next) {
int y = edge[i].e;
in[y]--;
if (in[y] == )
q.push(y);
}
}
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n, m, x, y;
scanf("%d%d", &n, &m);
init();
for (int i = ; i <= n; i++)
in[i] = , num[i] = , dp2[i] = dp[i] = ;
for (int i = ; i <= m; i++)
scanf("%d%d", &x, &y), add(x, y), add2(y, x), in[y]++;//正向反向各存一图,正向跑拓扑,反向求期望
solve(n);//求拓扑序
dp[a[n]] = ;
for (int x = n; x >= ; x--) {//期望dp日常倒推
if (a[x] != n) dp[a[x]] += num[a[x]] + , dp[a[x]] /= num[a[x]];//num[i]为与i点相连的点数
num[a[x]] = ;
for (int i = head2[a[x]]; i != -; i = edge2[i].next) {
int y = edge2[i].e;
dp[y] += dp[a[x]];
num[y]++;
}
}
dp2[n] = ;
for (int x = n; x >= ; x--) {
if (a[x] != n) dp2[a[x]] += (num[a[x]] + ) * dp[a[x]], dp2[a[x]] /= num[a[x]];
for (int i = head2[a[x]]; i != -; i = edge2[i].next) {
int y = edge2[i].e;
dp2[y] += dp2[a[x]];
num[y]++;
}
}
printf("%.2lf\n", dp2[]);
}
}

最新文章

  1. myecplise 中文乱码
  2. js生成一个以零开头的八位数并且依次递增
  3. Python—装饰器
  4. NYOJ109 数列转换 【守恒法】
  5. 【转载】cocos2d-x2.2.3和android的平台环境
  6. CodeForces 678C Joty and Chocolate
  7. Hibernate中Session之get和load方法的真正区别
  8. [转载]vb 时间戳与时间互转
  9. java执行post请求,并获取json结果组成想要的内容存放本地txt中
  10. 【M2】软件工程终期总结报告——阅读作业
  11. WPF工具开发: 第三库选择
  12. 2019.03.23 Http
  13. [ Linux运维学习 ] 路径及实战项目合集
  14. 【Hive学习之一】Hive简介
  15. cookie的参数
  16. 如何在 CentOS 7 中安装或升级最新的内核
  17. Python3基础 if elif 示例 判断一个数在哪个区间内
  18. ModelAndView 配置与使用
  19. C语言数组元素的查询
  20. es入门教程

热门文章

  1. 【UOJ#349】[WC2018] 即时战略
  2. H5 图片上传
  3. MySQL数据库2表的增删改查
  4. React native 之 Promise
  5. sed的一些应用
  6. win10+VS2015+opencv3.4.0配置方法
  7. NOIP2012 洛谷P1083 借教室
  8. 模拟赛DAY 2 T2不老梦
  9. C#中查找或结束程序域中的主、子进程
  10. java valueOf