Codeforces Round #130 (Div. 2) C. Police Station
题目链接:http://codeforces.com/contest/208/problem/C
思路:题目要求的是经过1~N的最短路上的某个点的路径数 / 最短路的条数的最大值。一开始我是用spfa得到从1开始的最短路和从N开始的最短路,然后分别从N开始记忆化搜索,得到从1到达最短路径上的u的路径条数,记作dp1[u], 然后再从1开始搜,得到最短路径上从N到达某个点u的路径条数,记作dp2[u],于是经过某个点u的最短路径数目为dp1[u] * dp2[u],然后只需枚举u求最大值即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std; const int MAX_N = (100 + 10);
int N, M;
long long dp1[MAX_N], dp2[MAX_N];
int vis[MAX_N], dist1[MAX_N], dist2[MAX_N];
vector<int > g[MAX_N]; void spfa(int st, int ed, int *dist)
{
memset(vis, 0, sizeof(vis));
queue<int > que;
que.push(st);
dist[st] = 0;
while (!que.empty()) {
int u = que.front(); que.pop();
vis[u] = 0;
REP(i, 0, (int)g[u].size()) {
int v = g[u][i];
if (dist[u] + 1 < dist[v]) {
dist[v] = dist[u] + 1;
if (!vis[v]) { vis[v] = 1; que.push(v); }
}
}
}
} long long dfs1(int u, int fa)
{
if (u == 1) return dp1[u] = 1;
if (~dp1[u]) return dp1[u];
long long ans = 0;
REP(i, 0, (int)g[u].size()) {
int v = g[u][i];
if (v != fa && dist1[v] + 1 == dist1[u]) {
ans += dfs1(v, u);
}
}
return dp1[u] = ans;
} long long dfs2(int u, int fa)
{
if (u == N) return dp2[u] = 1;
if (~dp2[u]) return dp2[u];
long long ans = 0;
REP(i, 0, (int)g[u].size()) {
int v = g[u][i];
if (v != fa && dist2[v] + 1 == dist2[u]) {
ans += dfs2(v, u);
}
}
return dp2[u] = ans;
} int main()
{
while (cin >> N >> M) {
FOR(i, 1, N) g[i].clear();
FOR(i, 1, M) {
int u, v; cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
memset(dist1, 0x3f, sizeof(dist1));
memset(dist2, 0x3f, sizeof(dist2));
spfa(1, N, dist1);
spfa(N, 1, dist2);
memset(dp1, -1, sizeof(dp1));
memset(dp2, -1, sizeof(dp2));
long long a = dfs1(N, -1);
double ans = 1.0;
dfs2(1, -1);
FOR(i, 1, N) if (dp1[i] >= 1 && dp2[i] >= 1) {
if (i == 1 || i == N) ans = max(ans, 1.0 * dp1[i] * dp2[i] / a);
else ans = max(ans, 2.0 * dp1[i] * dp2[i] / a);
}
printf("%.9f\n", ans);
}
return 0;
}
后来看了别人的做法,发现有更加简单的做法,直接用floyd做就可以了。dist[u][v]表示u到v的最短路径长度,dp[u][v]表示此最短路径长度对应的最短路径数目,然后就是更新的时候注意一下就可以了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std; const int MAX_N = (100 + 100);
int N, M;
long long dist[MAX_N][MAX_N], dp[MAX_N][MAX_N]; int main()
{
while (cin >> N >> M) {
memset(dist, 0x3f, sizeof(dist));
memset(dp, 0, sizeof(dp));
FOR(i, 1, M) {
int u, v; cin >> u >> v;
dist[u][v] = dist[v][u] = 1;
dp[u][v] = dp[v][u] = 1;
}
FOR(k, 1, N) {
FOR(i, 1, N) {
FOR(j, 1, N) if (dist[i][k] + dist[k][j] <= dist[i][j]) {
if (dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
dp[i][j] = dp[i][k] * dp[k][j];
}
else {
dp[i][j] += dp[i][k] * dp[k][j];
}
}
}
}
double ans = 1.0;
FOR(i, 2, N - 1) {
if (dist[1][i] + dist[i][N] == dist[1][N]) ans = max(ans, 2.0 * dp[1][i] * dp[i][N]/ dp[1][N]);
}
printf("%.7f\n", ans);
}
return 0;
}
Codeforces Round #130 (Div. 2) C. Police Station的更多相关文章
- Codeforces Round #130 (Div. 2) C - Police Station 最短路+dp
题目链接: http://codeforces.com/problemset/problem/208/C C. Police Station time limit per test:2 seconds ...
- Codeforces Round #408 (Div. 2) D - Police Stations
地址:http://codeforces.com/contest/796/problem/D 题目: D. Police Stations time limit per test 2 seconds ...
- Codeforces Round #130 (Div. 2)
A. Dubstep 字符串模拟. string.find()用法 string str; size_t pos = str.find("WUB"); // 返回匹配的第一个位置 ...
- Codeforces Round #130 (Div. 2) A. Dubstep
题目链接: http://codeforces.com/problemset/problem/208/A A. Dubstep time limit per test:2 secondsmemory ...
- Codeforces Round #244 (Div. 2) A. Police Recruits
题目的意思就是找出未能及时处理的犯罪数, #include <iostream> using namespace std; int main(){ int n; cin >> ...
- Codeforces Round #408 (Div. 2) D. Police Stations(最小生成树+构造)
传送门 题意 n个点有n-1条边相连,其中有k个特殊点,要求: 删去尽可能多的边使得剩余的点距特殊点的距离不超过d 输出删去的边数和index 分析 比赛的时候想不清楚,看了别人的题解 一道将1个联通 ...
- Codeforces Round #580 (Div. 1)
Codeforces Round #580 (Div. 1) https://codeforces.com/contest/1205 A. Almost Equal 随便构造一下吧...太水了不说了, ...
- Codeforces Round #366 (Div. 2) ABC
Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...
- Codeforces Round #354 (Div. 2) ABCD
Codeforces Round #354 (Div. 2) Problems # Name A Nicholas and Permutation standard input/out ...
随机推荐
- poj 1797(并查集)
http://poj.org/problem?id=1797 题意:就是从第一个城市运货到第n个城市,最多可以一次运多少货. 输入的意思分别为从哪个城市到哪个城市,以及这条路最多可以运多少货物. 思路 ...
- mysql创建用户
mysql创建用户 创建用于localhost连接的用户并指定密码 mysql> create user 'pcom'@'localhost' identified by 'aaa7B2249' ...
- vSphere Client无法连接到服务器 出现未知错误的解决方法
VMware ESXi服务器虚拟机在正常使用过程中,有时候会突然出现远程连接不上的问题,那么这个时候使用vSphere Client连接会出现如下错误: 虽然连接不上,但是可以ping通,所以分析有可 ...
- MySQL 利用SQL线程对Binlog操作
背景: 对于MySQL的binlog的查看都是用其自带的工具mysqlbinlog进行操作的,其实还有另一个方法来操作binlog,就是Replication中的SQL线程去操作binlog,其实bi ...
- 全能直播王PC版-0707-full_codecs
全能直播王是一款高清流畅的全平台的电视直播应用,让您随时随地看高清电视直播. [全能特色] 1. 收录全国1400多个直播频道,包括湖南卫视.江苏卫视.浙江卫视等热门频道. 2. 频道多线路自动选择, ...
- Mathematics:Semi-prime H-numbers(POJ 3292)
Semi-prime H-numbers 题目大意,令4n+1的数叫H数,H数素数x的定义是只能被x=1*h(h是H数),其他都叫合数,特别的,当一个数只能被两个H素数乘积得到时,叫H-semi数 ...
- Tomcat中文乱码问题的原理和解决方法
1) 更改 D:\Tomcat\conf\server.xml,指定浏览器的编码格式为“简体中文”: 方法是找到 server.xml 中的 <Connector port="8080 ...
- 【leetcode】Number of 1 Bits (easy)
做太多遍了,秒杀. class Solution { public: int hammingWeight(uint32_t n) { ; ), num++); return num; } };
- iOS 多线程及其他补充
NSOperation NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类 NSInvocationOperation 如果直接执行NSInvocationOperatio ...
- osgearth使用prjected投影
In projected mode, you have to specify a map profile (i.e. a map projection). You also need to tell ...