ICPC Northwestern European Regional Programming Contest E ETA
题目描述 :
给你一个分数,你要构造一幅图。
开始时,你等概率的传送到图上的一个点,你沿着最短的路径走到节点1。
你需要构造一张图使得路程的期望等于这个分数
基本思路:
我们能够发现我们需要构造的是一棵树,路程的期望值即为
∑
i
=
1
n
d
e
p
i
n
\sum_{i=1}^n dep_i \over n
n∑i=1ndepi
首先我们将这个分数进行通分,那么这棵树的大小为
b
b
b找到一个
(
a
,
b
)
(a,b)
(a,b) 对,使得这颗树能被构造
我们能发现最小的期望为 b − 1 b-1 b−1,即所有节点连在 1 1 1 上,最大期望为 b ∗ ( b + 1 ) 2 b*(b+1)\over 2 2b∗(b+1),即构成一条链。如果通分找不到满足 a a a 的 b b b,则报告非法。
若找到合法的 ( a , b ) (a,b) (a,b) 对,我们先把所有的点连成链,每次将深度最大的点上移一个单位,就能得到合法的树
代码:
#include <bits/stdc++.h>
using namespace std;
// #define int long long int
#define Paddi ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
int f(int x)
{
return (1 + x) * x / 2;
}
int main()
{
int a, b;
char ch;
cin >> a >> ch >> b;
bool find = false;
for (int i = 1; i * b <= 1e6; i++)
{
int ta = a * i, tb = b * i;
if ((f(tb - 1) >= ta) and (tb - 1 <= ta))
{
a = ta, b = tb;
find = true;
break;
}
}
if (find == false)
{
cout << "impossible" << endl;
}
else
{
b--;
vector<int> dep(b + 100);
dep[0] = 1;
int now = (b * (1 + b) / 2);
priority_queue<pair<int, int>> q1;
for (int i = 2; i <= b + 1; i++)
q1.push({i - 1, i});
while (now != a)
{
pair<int, int> t = q1.top();
q1.pop();
t.first--;
q1.push(t);
now--;
}
vector<int> ans(b + 100);
while (q1.size())
{
pair<int, int> t = q1.top();
q1.pop();
ans[t.second] = t.first;
}
for (int i = 2; i <= b + 1; i++)
dep[ans[i]] = i;
cout << b + 1 << " " << b << endl;
for (int i = 2; i <= b + 1; i++)
cout << i << " " << dep[ans[i] - 1] << endl;
}
return 0;
}