time limit: 1 sec
memory limit: 162 mb
自從明明學了樹的結構,就對奇怪的樹產生了興趣......給出標號為1到n的點,以及某些點最終的度數,允許在
任意兩點間連線,可產生多少棵度數滿足要求的樹?
第一行為n(0 < n < = 1000),
接下來n行,第i+1行給出第i個節點的度數di,如果對度數不要求,則輸入-1
乙個整數,表示不同的滿足要求的樹的個數,無解輸出031
-1-1
2兩棵樹分別為1-2-3;1-3-2
解答這道題需要用到乙個叫perfur sequence(以下簡稱ps)的知識,對於一顆有n個節點的樹,它與乙個長度為n-2的ps一一對應,那麼它們的對應方式如何呢?
將一棵樹轉化為ps:
假設我們有一顆樹,其中有如下邊:1-2,1-3,2-4,2-5,3-6,3-7(其實就是節點標號1~7的完全二叉樹),我們先取標號最小的葉子節點4,記錄此時與其相連的節點,得到了ps的第一位數字:2,然後刪除節點4。按照上面的步驟,取5得2,取2得1,取1得3,取6得3。我們這個時候就得到了這個長為5的ps:2 2 1 3 3,顯然,對於一棵樹只能得到乙個ps,也就是每棵樹只對應乙個ps。
將乙個ps轉化為樹:
使用上面的ps:2 2 1 3 3 。首先這是乙個長為5的ps,那就意味這這棵樹有7個節點,顯然由上面我們可以知道每個節點的度數=它在ps中出現過的次數+1 。於是我們對於每乙個節點建立乙個表來描述它們的權值:
1 2 3 4 5 6 7
2 3 3 1 1 1 1
此時取度數為1的標號最小的節點4,使其與ps中的第一位數字對應標號的節點2相連,建邊4-2,然後刪除ps中第一位數字2,此時ps為2 1 3 3,同時在表中將2和4的權值分別減去1:
1 2 3 4 5 6 7
2 2 3 0 1 1 1
節點5與節點2相連,建邊5-2,ps變為1 3 3,權值表變為:
1 2 3 4 5 6 7
2 1 3 0 0 1 1
節點2與節點1相連,建邊2-1,ps變為3 3,權值表變為:
1 2 3 4 5 6 7 1
0 3 0 0 1 1
節點1與節點3相連,建邊1-3,ps變為3,權值表變為:
1 2 3 4 5 6 7
0 0 2 0 0 1 1
節點6與節點3相連,建邊6-3,ps清空,權值表變為:
1 2 3 4 5 6 7
0 0 1 0 0 0 1
最後在連線節點3與節點7,得到下面這些邊:4-2、5-2、2-1、1-3、6-3、7-3,很容易看出這就是我們上面的那顆樹。
在轉換過程中我們能發現,ps編碼生成的樹是唯一的,結合上面的結論,我們得出了ps編碼的性質:乙個ps編碼和一棵樹一一對應。
有了這個知識後,我們該如何解決這個問題呢?
首先,無解的情況很好判斷,這裡就不過多說明了。
對於有解的情況,由上面的過程我們知道,乙個節點的度數-1等於它在ps中出現過的次數,假設我們有m個度數有限制的點,分別為d[i]。
設:sum=∑(d[i]-1),(1<=i<=m)。
那麼對於乙個ps,不同排列的種數為:
c(m,n-2)*((sum!)/(∏(d[i]-1)!)),(1<=i<=m)。
對於剩下的n-2-m個位置,我們就可以隨意排列剩下的n-m個點,於是總的方案就是:
c(m,n-2)*((sum!)/(
∏(d[i]-1)!
))*(n-m)^(n-2-m),(1<=i<=m)
這就是有解的情況下的答案,高精度是必須的。
**:
#include#define mod 1000000
#define ll long long
using namespace std;
int n,m,tot,cnt,d[1005],num[1005],pri[1005],ans[1005],l=1;
bool jud(int x)
void getpri()
void solve(int a,int f)}}
}void mul(int x)
while (ans[l+1]>0) }
int main()
for (int i=1 ; i<=n ; i++)
if (d[i]==-1)
m++;
else
}if(tot>n-2)
solve(n-2,1);
solve(n-2-tot,-1);
for(int i=1;i<=n;i++)
if(d[i])
solve(d[i],-1);
for(int i=1;i<=cnt;i++)
while(num[i]--)
mul(pri[i]);
for(int i=1;i<=n-2-tot;i++)
mul(m);
for(int i=l;i>0;i--)
if(i==l)
printf("%d",ans[i]);
else
printf("%06d",ans[i]);
return 0;
}
狡猾的商人 bzoj1202,HNOI2005
ac通道 分析 因為每月的總收入可以為正,也可以為負,所以要比較兩個區間是否相符,當且僅當它們邊界都相同時才能比較。我們設w i 表示第1 i個月的總收入與第1 fa i 1 個月的總收入之差,及第fa i i個月的總收入。如圖。若i 1,j在同乙個集合中,則第i j個月的總收入為w j w i 1...
bzoj1005 hnoi2008 明明的煩惱
time limit 1 sec memory limit 162 mb submit 3157 solved 1262 submit status discuss 自從明明學了樹的結構,就對奇怪的樹產生了興趣.給出標號為1到n的點,以及某些點最終的度數,允許在任意兩點間連線,可產生多少棵度數滿足要...
BZOJ 1005 HNOI2008 明明的煩惱
給定一棵n個節點的樹的節點的度數,其中一些度數無限制,求可以生成多少種樹。用到了prufer數列的知識。度娘 prufer數列 是由有乙個對於頂點標過號的樹 標號樹 轉化來的數列,點數為n的樹轉化來的prufer數列長度為n 2。由heinz prufer於1918年在證明cayley定理時首次提出...