观光铁路
暴力搜索+剪枝
这题很麻烦,一开始找不到很好的办法,大概搜了一下搜到了概率dp,学了一下,发现用不上,因为路径可以无限长,递推没有终点。
然后看到数据量
n
≤
21
n\le 21
n≤21,诶数据量好小,那直接搜图吧,DFS递归搜索,然后记录起点,当前点,父节点,当前概率,当前路径长度,遍历子节点,发现父节点跳过,发现起点就可以求当前路径的期望累加到结果里。
但我忽略了环,这个绕起来没完,即使剪枝
p
(
n
+
1
)
<
1
e
−
13
p(n+1)<1e-13
p(n+1)<1e−13时间复杂度还是太高了,再剪枝
n
<
25
n<25
n<25答案偏离又太多,没法保证1e-9的误差值,难办。
#include<iostream>
using namespace std;
const int MAX = 100;
int tot = 0, to[MAX], head[MAX], num[MAX], cnext[MAX];
int n, m;
double ans;
void addedge(int u, int v) {
to[++tot] = v;
cnext[tot] = head[u];
head[u] = tot;
num[u]++;
}
void DFS(int c, int u, int f, double p, int n) {;
if ((p*(n+1)) < 1e-13)return;
//if (n > 25)return;
for (int k = head[u]; k; k = cnext[k]) {
int v = to[k];
if (v == f)continue;
double np;
if(f!=0)np = p / (num[u] - 1);
else np = p / num[u];
if (v == c) { ans += np * (n + 1); continue; }
DFS(c, v, u, np, n + 1);
}
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
int u, v;
cin >> u >> v;
addedge(u, v);
addedge(v, u);
}
for (int i = 1; i <= n; i++) {
ans = 0;
DFS(i, i, 0, 1, 0);
printf("%.12f\n", ans);
}
system("pause");
return 0;
}
规律总结
做着做着发现这个期望可以和图中的度联系起来,这个期望值就正好是图中的总度数比上这个点的度数。具体为什么可能涉及了概率论知识,我先去看看概率论,可能有证明思路了再补上吧。
#include<iostream>
using namespace std;
const int MAX = 100;
int num[MAX];
int n, m;
int main()
{
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
int u, v;
cin >> u >> v;
num[u]++;
num[v]++;
}
for (int i = 1; i <= n; i++) {
double p = m * 2.0 / num[i];
printf("%.12f\n", p);
}
return 0;
}