题目链接: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的更多相关文章

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

  2. Codeforces Round #408 (Div. 2) D - Police Stations

    地址:http://codeforces.com/contest/796/problem/D 题目: D. Police Stations time limit per test 2 seconds ...

  3. Codeforces Round #130 (Div. 2)

    A. Dubstep 字符串模拟. string.find()用法 string str; size_t pos = str.find("WUB"); // 返回匹配的第一个位置 ...

  4. Codeforces Round #130 (Div. 2) A. Dubstep

    题目链接: http://codeforces.com/problemset/problem/208/A A. Dubstep time limit per test:2 secondsmemory ...

  5. Codeforces Round #244 (Div. 2) A. Police Recruits

    题目的意思就是找出未能及时处理的犯罪数, #include <iostream> using namespace std; int main(){ int n; cin >> ...

  6. Codeforces Round #408 (Div. 2) D. Police Stations(最小生成树+构造)

    传送门 题意 n个点有n-1条边相连,其中有k个特殊点,要求: 删去尽可能多的边使得剩余的点距特殊点的距离不超过d 输出删去的边数和index 分析 比赛的时候想不清楚,看了别人的题解 一道将1个联通 ...

  7. Codeforces Round #580 (Div. 1)

    Codeforces Round #580 (Div. 1) https://codeforces.com/contest/1205 A. Almost Equal 随便构造一下吧...太水了不说了, ...

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

  9. Codeforces Round #354 (Div. 2) ABCD

    Codeforces Round #354 (Div. 2) Problems     # Name     A Nicholas and Permutation standard input/out ...

随机推荐

  1. 【leetcode】Next Permutation

    Next Permutation Implement next permutation, which rearranges numbers into the lexicographically nex ...

  2. Qt Connect 信号 槽

    信号和槽机制是 QT 的核心机制 .信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方.信号和槽是 QT 自行定义的一种通信机制,它独立于标准 ...

  3. 2. javacript高级程序设计-在HTML中使用JavaScript

    1.1 <script>元素 向HTML页面中插入JavaScript的主要方法,就是使用<script>元素,<script>元素定义了一下6个元素: (1). ...

  4. SAP ALV OO 选择行打印

    &---------------------------------------------------------------------* *& Report  ZSDF001 * ...

  5. Mathematics:X-factor Chains(POJ 3421)

    X链条 题目大意,从1到N,1 = X0, X1, X2, …, Xm = X中间可以分成很多数,另Xi < Xi+1 Xi 可以整除Xi+1 ,求最大长度m和m长度的链有多少条 思路: 很简单 ...

  6. uva 401.Palindromes

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  7. H5 多个视频 循环播放效果

    跟轮播效果差不多 页面HTML结构 <video id="myvideo" width="100%" height="auto" co ...

  8. 【leetcode】Remove Duplicates from Sorted List (easy)

    Given a sorted linked list, delete all duplicates such that each element appear only once. For examp ...

  9. 【XLL API 函数】xlGetBinaryName

    用于返回由 xlDefineBinaryName 函数定义的名称数据句柄.定义的名称和工作簿一起保存,我们可以在任意时间访问这个名称. 原型 Excel12(xlGetBinaryName, LPXL ...

  10. docker基础命令

    docker version                                                                                       ...