圖計數(兩個思想,和一個去重技巧,賊重要,紫題,非常有東西)

cn是大帅哥886發表於2024-08-12
https://www.luogu.com.cn/problem/AT_abc180_f
第3題 圖計數 檢視測評資料資訊

給n個節點m條邊,構造一些無向圖,構造出來的圖需要滿足以下條件:

(1)圖中沒有自環

(2)圖中每個點的度最大是2

(3)圖中連通塊大小最大為L

問能構造出多少個這樣的圖出來,答案可能很大,對1e9+7取模

輸入格式

第一行三個整數n,m,L

2<=n<=300,1<=m,L<=n

輸出格式

一個整數

輸入/輸出例子1

輸入:

3 2 3

輸出:

3

樣例解釋

在瞭解此題前,我們先學一些前置知識

前置知識


環和鏈的重複性


1.對於一個鏈,反轉一下還是同一副圖,例如:

2.對於一個環,把圖翻過來還是同一幅圖

想成立體空間,把這個圖反轉過來,這樣的圖是同一個圖

根據點數計算不同鏈的數量


對於一個鏈

n個節點,構成的不同圖數量
n! / 2

很簡單,因為會有重複,把鏈反轉還是同一個鏈,所以結果要除二

根據點數計算不同環的數量(圓排列,項鍊排列)


對映思想


今天的第一個思想:運用對映思想
如果算A集合很難算,但我知道B集合有多少個,且B與A有關係,那麼就可以用B對映A

例如,我們想求A集合內成員數量,但是正面無法算,可是我們知道B集合有5個成員,且1個A集合相當於5個B集合,那麼A集合成員數量就可以透過B集合成員數量推出來,即 A集合數量=B集合數量*5 = 5*5 = 25

這裡引入幾個概念

圓排列


圓排列:對於n個節點能構成多少個不同的圓,注意是二維(2D)的,就是在一個二維平面,順時針看不一樣才算不同排列

正面算很難是吧,假設此時n=3

根據對映思想,我們可以算出全排列數量,即線性排列數量,很好算嘛,n! 種

然後我們再算一個圓(任意一個),它對應的排列數量,怎麼求?我們可以先暫時割掉一個邊,然後再dfs就出來順序了,如上圖

先割掉(1,3)這條邊,我們dfs一遍,就是{1,2,3},那麼這就是一個排列了,由於一共可以割掉n條邊,所以有n種

一個圓對應這麼多個排列數量,我們總共有那麼多個排列數量,我們用總共/單個,不就算出來數量了嗎

即 n! / n = (n-1)!

簡化:假設有n個點,那麼有n!種線性排列,有n個圓上面的排列(n個切割點)

至此推出了圓排列公式:(n-1)!

項鍊排列


項鍊排列:對於n個節點能構成多少個不同的圓,注意是二維(3D)的,就是在一個三維平面,順時針看不一樣也算同一個排列

假設有n個點,那麼有n!種線性排列,有(n-1)!圓排列,我們觀察一下圓排列和項鍊排列可以觀察出一個規律:

假設n=3,那麼這個項鍊排列有2個(固定著1,把圖反轉一下,運用空間想象力哈),根據圓排列計算公式,(n-1)!=(3-1)!=2!=2,那麼把這些值加在一起就可以發現規律了!

圓排列是項鍊排列的2倍
至此推出了項鍊排列公式:(n-1)! / 2

本題做法


根據題意,圖會構成:

1) 一條鏈,邊數=點數-1
2) 一個環,邊數=點數

邊數和點數有一種對應關係,所以我們可以根據點數推邊數

f[i][j]:一共考慮了i個點,j條邊,連通塊數量小於等於L的方案數

如果直接算等於L的方案數比較難,我們可以用算出來的DP,求出L - (L-1) 的方案數就是L的方案數了

這就是做差思想

我們假設新加入k個點,和圖原來的構成:


1)鏈的情況

現在加入k個點,相當於加入k-1條邊
在他之前的圖,有i-k個點,j-(k-1)條邊

那麼i,j的狀態肯定由i-k,j-(k-1)轉移過來的對吧

我們還需要考慮貢獻。

這k個點從要考慮從哪個集合裡面選,選出來後的點還有考慮如何排列。

我們先考慮從那裡選對吧,答案很顯然,從n個點裡面選,那麼有多少選擇方法?

首先之前圖的點數不可再選了,那麼剩餘的就是可以選的

總共可選點數 - 之前圖的點數
C(n-(i-k), k)

注意重複情況!我們選k個節點,可以分別考慮每個點
第一次:選1 2 3
第二次:選1 3 2
那不就重複了嗎,要去重

去重技巧:可以理解為排序,它是有一種順序的。我們讓最小點先進入選擇的序列中,一定要放進去!這樣後面選進來的點就不重複了


即 C(n-(i-k)-1, k-1)

選出來後考慮如何排列

這很簡單,選出來了k個點,那麼就是 k!種排列,由於選出來的點最終構成鏈,那麼有重複情況/2即可,前置知識嘛!

排列數量:k! / 2

轉移方程整理一下變成:

f[i][j] = (f[i][j] + f[i-k][j-k+1] * C(n-i+k-1, k-1) * k! / 2)


2)環的情況
現在加入k個點,相當於加入k條邊
原來圖點數 i-k,邊數 j-k

和鏈情況同樣,不過注意由於選出來的k個點要構成一個環,排列數量就是項鍊排列,也就是 (n-1)! / 2

轉移方程:

f[i][j] = (f[i][j] + f[i-k][j-k] * C(n-i+k-1, k-1) * (k-1

相關文章