所謂內向樹,就是樹上的邊是由兒子指向父親
來看乙個題
元首把花園分為 nn
n 行 mm
m 列的網格。每個格仔中都可以放置乙個標識,指向上、下、左、右四個方向中的任意乙個。元首位於乙個格仔時,會按照其中標識所指的方向進入周圍的格仔,或者走出花園(即目的格仔不在網格之內)。舉個例子 —— 對於下面的放置方式,元首從第 33
3 行第 22
2 列的格仔開始,會沿著以紅色標出的路徑走出花園;從第 22
2 行第 22
2 列的格仔開始,則會在以藍色標出的環路內不斷地行走。
← →↓← ↑ ←↓
← ↑→↓ ←
元首已經設計好了大部分格仔的標識。元首用字元l
、r
、u
、d
分別表示指向左、右、上、下四個方向的標識,用字元.
表示未決定的格仔。現在,元首希望將每個.
替換為l
、r
、u
、d
中任意一種,使得從花園中的任意乙個格仔出發,按照上述規則行走,都可以最終走出花園。
你需要編寫程式幫助元首計算替換的不同方案數。兩個方案不同當且僅當存在乙個格仔,使得兩個方案中該格仔內的標識不同。當然,由於答案可能很大,只需給出方案數除以 109+710^9 + 710
9
+7所得的餘數即可。
對於此題,我們對於邊界外建立乙個點(n*m+1),網格每個點向指出去的點連邊,未知的點,它的連邊方式有4種,求生成樹的個數
這題的生成樹邊是單向的,且都由孩子指向父親,我們管它叫內向樹的生成樹計數,然後結論就是:另鄰接矩陣為g,出度矩陣為d,那麼d-g的任意乙個n-1行n-1列子矩陣的行列式就是生成樹的個數。
你要問我為什麼是這樣的,我這麼菜,怎麼可能會嘛。。。
因為這題的點數太大了,如果直接建立矩陣肯定是不行的,但是我們發現對答案有影響的就是指向未知的點,那麼就可以只提取出那些關鍵點(題目保證了關鍵點個數只有300個),那麼我們在這300個點之間建立關係求行列式就好了。
注意的是一開始需要判斷,因為已知方向的點可能已經構成環了,我的方法如下:一開始對於那些已知方向的點,用並查集縮點,然後已知方向的點的聯通塊只能有乙個(指向n*m+1)。
#include#include#include#include#includeusing namespace std;
const int maxn = 305;
const int mod = 1000000007;
int d[maxn][maxn], g[maxn][maxn], f[maxn][maxn];
int n, m, t, i, j, k, fa[maxn * maxn], x[maxn], y[maxn], cnt, num[maxn * maxn];
int dx[4] = , dy[4] = ;
char s[maxn][maxn];
inline int find(int x)
inline int point(int x, int y)
inline int ksm(int x, int y, int z)
return b;
}int main()
int xx = find(point(i, j)), yy;
if (s[i][j] == 'u') yy = find(point(i - 1, j));
if (s[i][j] == 'd') yy = find(point(i + 1, j));
if (s[i][j] == 'l') yy = find(point(i, j - 1));
if (s[i][j] == 'r') yy = find(point(i, j + 1));
fa[xx] = yy;
}int block = 0;
for(i = 1; i <= n * m + 1; i ++)
if (find(i) == i) block ++;
if (block > cnt + 1)
for(i = 1; i <= cnt; i ++)
num[point(x[i], y[i])] = i;
for(i = 1; i <= cnt + 1; i ++)
for(j = 1; j <= cnt + 1; j ++)
g[i][j] = d[i][j] = 0;
num[n * m + 1] = cnt + 1;
for(i = 1; i <= cnt; i ++)
for(j = 0; j < 4; j ++)
for(i = 1; i <= cnt; i ++)
for(j = 1; j <= cnt; j ++)
int ans = 1;
for(i = 1; i <= cnt; i ++)
if (!k) continue;
if (k != i)
for(j = i + 1; j <= cnt; j ++)
}for(i = 1; i <= cnt; i ++)
ans = 1ll * ans * f[i][i] % mod;
if (ans < 0) ans += mod;
cout << ans << endl;
}}
生成樹計數
考慮簡單帶權無向圖的情況。約定這張圖為 g v,e n v m e e i u i,v i,w i 表示第 i 條邊,deg u 表示 u 所連邊的邊權和。mathbf a 滿足 mathbf a w i,j mathbf d 滿足 mathbf d i j deg i mathbf b 滿足 ma...
Lightning(生成樹計數)
原題 題意 n個點,任意兩個點之間可以連邊當且僅當距離不大於r,並且中間沒有其他邊。求生成樹個數。解析 判斷中間有沒有點可以直接n3for,也可以n2log,列舉每個點為起點,其他的點與之形成的向量用map比較是否存在即可。連完邊就用矩陣樹進行n3做就行了。include using namespa...
無標號生成樹計數
做模擬賽的時候碰到了,感覺稍微有點意思,寫來自己看。無標號有根樹 設f n 表示樹的大小為 n 的方案數,其生成函式f z n 0f nzn。考慮生成函式的組合意義,fn 1可以由若干個無序的不同大小的 若干個無序的相同大小的本質不同的子樹 拼成,對於大小為 k 的樹,作為多棵子樹時他可以貢獻的不同...