题意:
求
n
n
n个点
m
m
m条边的点有编号边无编号的满足以下条件的无向图个数:
1.
1.
1.不必是简单图或连通图
2.
2.
2.每个点度数最多是
2
2
2
3.
3.
3.最大连通块的大小恰好是
l
l
l
2
<
=
n
<
=
200
,
1
<
=
m
,
l
<
=
n
2<=n<=200,1<=m,l<=n
2<=n<=200,1<=m,l<=n
模
1
e
9
+
7
1e9+7
1e9+7
题解:
首先注意思考图的本质不同。首先要注意到你给一个连通块选的点的顺序不同,但是点的集合是一样的,这两种方案是相同的。
然后考虑这题最特别的一点要求,就是每个点的度数最多是 2 2 2,那么说明这个图的每一个连通块要么是一条链(包括单独一个点),要么是一个环。
我们很容易考虑一个状态: d p [ i ] [ j ] dp[i][j] dp[i][j]表示选了 i i i个点,有 j j j条边的方案数。但是这样有一个问题,就是我们不能很好的限制最大连通块大小恰好是 l l l。可能可以用一维 0 / 1 0/1 0/1来记录这个状态是否选过大小是 l l l的块来做。但是标算的做法是用一个简单的容斥思想:用最大块大小最多是 l l l的答案减去最大块大小最多是 l − 1 l-1 l−1的答案。
这样我们想清楚怎么计算答案之后,就该考虑如何转移dp了。我们用分类讨论的办法考虑dp的转移。
这里首先说这题最关键的地方,也是我记录这题的主要原因,就是这里的计数需要先强制当前编号最小的没选过的点一定要选,尽管我们并不关心它具体是哪个点。这里关键问题是,不做这个强制直接乘组合数的话,会出现重复。举个例子:会出现先选1、2再选3、4和先选3、4再选1、2会被重复计算。当时我的一个想法是从小到大考虑块的大小,然后一次把相同大小的块一起考虑来更新答案,再除一个阶乘,但是答案还是不对,暂时没想好是写挂了还是数得就不对。
先讲正解做法,考虑转移。
1.加入一个单独的点,这个点形成一个新的连通块。
d
p
[
i
]
[
j
]
+
=
d
p
[
i
−
1
]
[
j
−
1
]
dp[i][j]+=dp[i-1][j-1]
dp[i][j]+=dp[i−1][j−1]
2.加入一条长度为
k
k
k的链(
2
<
=
k
<
=
l
2<=k<=l
2<=k<=l)。注意到链上的点可以随意排列,但是在图的意义下把一个排列翻转和原排列是等价的,所以要除
2
2
2。因为强制选编号最小的没选的点,于是组合数那里要减
1
1
1。
d
p
[
i
]
[
j
]
+
=
d
p
[
i
−
k
]
[
j
−
k
+
1
]
∗
C
n
−
(
i
−
k
)
−
1
k
−
1
∗
k
!
2
dp[i][j]+=dp[i-k][j-k+1]*C_{n-(i-k)-1}^{k-1}*\frac{k!}{2}
dp[i][j]+=dp[i−k][j−k+1]∗Cn−(i−k)−1k−1∗2k!
3.加入一个大小为
2
2
2的环
d
p
[
i
]
[
j
]
+
=
d
p
[
i
−
2
]
[
j
−
2
]
∗
C
n
−
(
i
−
2
)
−
1
2
−
1
dp[i][j]+=dp[i-2][j-2]*C_{n-(i-2)-1}^{2-1}
dp[i][j]+=dp[i−2][j−2]∗Cn−(i−2)−12−1
4.加入一个大小为
k
k
k的环(
k
>
2
k>2
k>2)。注意到环排列的公式是
(
n
−
1
)
!
(n-1)!
(n−1)!
d
p
[
i
]
[
j
]
+
=
d
p
[
i
−
k
]
[
j
−
k
]
∗
C
n
−
(
i
−
k
)
−
1
k
−
1
∗
(
k
−
1
)
!
2
dp[i][j]+=dp[i-k][j-k]*C_{n-(i-k)-1}^{k-1}*\frac{(k-1)!}{2}
dp[i][j]+=dp[i−k][j−k]∗Cn−(i−k)−1k−1∗2(k−1)!
这样就做完了,复杂度 O ( n ∗ k ∗ l ) O(n*k*l) O(n∗k∗l)
代码暂时没有。