博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Codeforces Round #356 (Div. 1) D. Bear and Chase 暴力
阅读量:5979 次
发布时间:2019-06-20

本文共 4385 字,大约阅读时间需要 14 分钟。

D. Bear and Chase

题目连接:

Description

Bearland has n cities, numbered 1 through n. There are m bidirectional roads. The i-th road connects two distinct cities ai and bi. No two roads connect the same pair of cities. It's possible to get from any city to any other city (using one or more roads).

The distance between cities a and b is defined as the minimum number of roads used to travel between a and b.

Limak is a grizzly bear. He is a criminal and your task is to catch him, or at least to try to catch him. You have only two days (today and tomorrow) and after that Limak is going to hide forever.

Your main weapon is BCD (Bear Criminal Detector). Where you are in some city, you can use BCD and it tells you the distance between you and a city where Limak currently is. Unfortunately, BCD can be used only once a day.

You don't know much about Limak's current location. You assume that he is in one of n cities, chosen uniformly at random (each city with probability ). You decided for the following plan:

Choose one city and use BCD there.

After using BCD you can try to catch Limak (but maybe it isn't a good idea). In this case you choose one city and check it. You win if Limak is there. Otherwise, Limak becomes more careful and you will never catch him (you loose).
Wait 24 hours to use BCD again. You know that Limak will change his location during that time. In detail, he will choose uniformly at random one of roads from his initial city, and he will use the chosen road, going to some other city.
Tomorrow, you will again choose one city and use BCD there.
Finally, you will try to catch Limak. You will choose one city and check it. You will win if Limak is there, and loose otherwise.
Each time when you choose one of cities, you can choose any of n cities. Let's say it isn't a problem for you to quickly get somewhere.

What is the probability of finding Limak, if you behave optimally?

Input

The first line of the input contains two integers n and m (2 ≤ n ≤ 400, ) — the number of cities and the number of roads, respectively.

Then, m lines follow. The i-th of them contains two integers ai and bi (1 ≤ ai, bi ≤ n, ai ≠ bi) — cities connected by the i-th road.

No two roads connect the same pair of cities. It's possible to get from any city to any other city.

Output

Print one real number — the probability of finding Limak, if you behave optimally. Your answer will be considered correct if its absolute error does not exceed 10 - 6.

Namely: let's assume that your answer is a, and the answer of the jury is b. The checker program will consider your answer correct if |a - b| ≤ 10 - 6.

Sample Input

3 3

1 2
1 3
2 3

Sample Output

0.833333333333

Hint

题意

有一个人,在一个图里面开始找罪犯了。

这个人有两天的抓捕机会,他会在每一天都有机会使用BCD机器,这个BCD机器会返回这个罪犯离他的距离是多少。

当然这个人要么在第一天去抓罪犯,要么在第二天去抓罪犯。

这个罪犯也不是一个傻逼,如果那个人第一天不抓他的话,那么第二天的时候,这个罪犯就会转移阵地。

然后现在问你,在最佳情况下,这个人抓住这个罪犯的概率是多少?

题解:

考虑最暴力的情况,枚举罪犯第一天哪儿,第二天在哪儿,枚举警察第一天在哪儿使用BCD,第二天在哪儿使用BCD

这个复杂度是n^4的,显然过不了,但是显然是对的。

我们优化一下。

暴力枚举这个警察第一天在哪儿使用BCD的地点A,暴力枚举BCD返回的距离a,再暴力枚举第二天使用BCD的地点B。

显然罪犯只有可能出现在三种位置,就是距离A地点距离为a,a-1,a+1的三个地方。

这样优化了一下之后,复杂度就变成n^3了,就可以直接莽过去了。

代码

#include
using namespace std;const double eps = 1e-6;const int maxn = 405;int d[maxn][maxn],n,m;double dis[maxn];double posi[maxn];vector
E[maxn];vector
f;void TAT(){ memset(d,127,sizeof(127));}double next(int p,int di){ double ans = 0; memset(posi,0,sizeof(posi)); for(int i=1;i<=n;i++) if(d[p][i]==di) for(auto v:E[i]) posi[v]+=1./n/E[i].size(); f.clear(); for(int i=1;i<=n;i++) if(posi[i]>eps) f.push_back(i); for(int i=1;i<=n;i++) { double tmp = 0; for(auto v:f) dis[d[i][v]]=max(dis[d[i][v]],posi[v]); for(auto v:f) { tmp+=dis[d[i][v]]; dis[d[i][v]]=0; } ans=max(ans,tmp); } return ans;}void QAQ(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j)d[i][j]=n+1; for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); d[a][b]=1; d[b][a]=1; E[a].push_back(b); E[b].push_back(a); } for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); double ans = 0; for(int i=1;i<=n;i++) { double tmp = 0; for(int di=0;di

转载地址:http://skoox.baihongyu.com/

你可能感兴趣的文章
什么是桥接?
查看>>
Kali Linux之速会BEEF & XSS攻击
查看>>
TUP第11期:腾讯、豆瓣精英实例诠释互联网研发之道
查看>>
一起谈.NET技术,深入理解string和如何高效地使用string
查看>>
一起谈.NET技术,ASP.NET MVC 2 验证消息本地化策略扩展
查看>>
面向对象封装的web服务器
查看>>
Metaspolit之端口扫描
查看>>
Springboot + Atomikos + Druid + Mysql 实现JTA分布式事务
查看>>
关于数据存储类型的一点分析
查看>>
SqlServer 线下讲座
查看>>
2011年年度总结
查看>>
团队-团队编程项目作业名称-项目进度
查看>>
Linux基础入门学习笔记之三
查看>>
写代码如何合理使用和优化我们的机器资源(CPU、内存、网络、磁盘)
查看>>
剑指offer---不用加减乘除做加法
查看>>
C# 配置文件读取与修改
查看>>
自定义RatingBar样式
查看>>
万能ViewHolder和基类适配器
查看>>
数据仓库之 - SQL Server 2008新的优化特性
查看>>
项目编写时的注意事项
查看>>