ADPC2-G 希望
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ADPC2-G 希望相关的知识,希望对你有一定的参考价值。
题意:
有A,B两棵树,对于一个1到n的全排列a[i],让树A中的点i和树B的节点a[i]连一条边,希望指数:两棵树和新加入的边构成的图中,环长为m的环的个数。数组a[]可以任意交换位置,且任意,随机,不限次数的交换。计算出期望情况下,两棵树的希望指数
n≤300,3≤m≤7
题解:
期望=概率 * 对应的权值
在本题中概率肯定是
1
n
!
\\frac{1}{n!}
n!1,因此需要求所有情况下环长为m的环的个数
我们开始找环的分布情况,一定是左侧的点和右侧的点通过之间加的点形成环,如图,图中环长为6
且所有环用到中间新建边只能为两条边,可能会疑惑,为什么?像图中情况,用到的新建边的数量为4,不是2,但是图中环的长度为8(这已经是新建边4所对应的环最小长度),而题目保证所求环长<=7,刚好不行。也就是其实题目是隐含着新建边最多用两条,不可能更多
我们确定了中间边只能用2,那就好说了,比如让你求环为x的数量,x先减2,y=x-2,然后就是两个树一共构成长度为y,因此我们预先处理出两个子树分别能组成长度为len的边的数量,用桶来存。比如:tong1[i]:表示在树A中长度为i的边的数量。那么答案就:
t
o
n
g
1
[
i
]
∗
t
o
n
g
2
[
m
−
i
−
2
]
∗
2.0
∗
(
(
n
−
2
)
)
tong1[i]*tong2[m-i-2]*2.0*((n-2))
tong1[i]∗tong2[m−i−2]∗2.0∗((n−2))
i是树A需要提供的边,m-i-2是树B需要提供的边,乘2.0是因为边可以交叉和不交叉来,正好两种,而最后(n-2)!是什么?我们之前说过最多用新增边为2,那么说明左右各有两个点要被占用(因为一个边有两个点),而其他的点可以任意排列,剩下的点就是(n-2)个,任意排列就是阶乘
再讲一些细节:
比如树上所有路径长度,可以用floyd来求,因为答案要乘(n-2)!,而最终答案还要除以n!,所以直接除以n*(n-1)即可
代码:
#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{
x= 0;
char c= getchar();
bool flag= 0;
while (c < '0' || c > '9')
flag|= (c == '-'), c= getchar();
while (c >= '0' && c <= '9')
x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();
if (flag)
x= -x;
read(Ar...);
}
template <typename T> inline void write(T x)
{
if (x < 0) {
x= ~(x - 1);
putchar('-');
}
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#else
startTime = clock ();
freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#else
endTime= clock();
printf("\\nRun Time:%lfs\\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn=400;
vector<int>a[maxn],b[maxn],g[maxn];
int L[maxn];
int x[maxn][maxn];
int y[maxn][maxn];
int tong1[maxn],tong2[maxn];
int main()
{
//rd_test();
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
x[i][j]=1e9;
y[i][j]=1e9;
}
}
for(int i=1;i<n;i++){
int u,v;
read(u,v);
x[u][v]=x[v][u]=1;
}
for(int i=1;i<n;i++){
int u,v;
read(u,v);
y[u][v]=y[v][u]=1;
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
x[i][j]=min(x[i][j],x[i][k]+x[k][j]);
y[i][j]=min(y[i][j],y[i][k]+y[k][j]);
}
}
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(i==j)continue;
if(x[i][j]==1e9)continue;
if(y[i][j]==1e9)continue;
tong1[x[i][j]]++;
tong2[y[i][j]]++;
}
}
double ans=0;
for(int i=1;i<=m-3;i++){
ans=ans+1.0*tong1[i]*tong2[m-i-2]*2.0/(1.0*n*(n-1));
}
printf("%.4lf\\n",ans);
//Time_test();
}
以上是关于ADPC2-G 希望的主要内容,如果未能解决你的问题,请参考以下文章