【cf859E】Desk Disorder
阿新 • • 發佈:2018-10-28
n-1 portal iostream string max 計算 urn ++i 位置
Portal --> cf859E
Solution
?? 我們可以將每一個人看成一條邊,將位置看成點,然後一個人在新的方案中可以選擇的位置就是這條邊連接的兩個點,然後我們就得到了一個圖
? 註意到這個圖可能包含多個連通塊,每個連通塊可以獨立計算,那麽最後的答案應該就是各個連通塊計算結果的乘積,那麽現在我們的問題就是怎麽算一個連通塊內的答案
?? 考慮一個包含\(n\)個點的連通塊,我們來分析一下這個連通塊的性質:首先因為這是一個連通塊,所以邊數\(m>=n-1\),然後註意到這題中有一個性質:原方案中沒有兩個人選的是同一個位置(點),所以我們可以得到邊數\(m<=n\)
? 所以一個包含\(n\)個點的連通塊只可能有兩種情況:
1、\(m=n-1\):這個時候是一棵樹,那麽答案就應該是\(n\)(樹中的節點個數),具體的話就是考慮哪個節點沒有人選,所以就有\(n\)種方案
2、\(m=n\):這個時候如果是一個基環樹,考慮環中的邊數和點數相同,所以環中所有的點只能被環上的邊選,這樣一來樹中能選的點數和要選的邊數相等,所以樹中的方案是唯一的,環中的方案只有兩種,所以這個時候有\(2\)中方案;但是!如果說這個環是個自環,那就只有一種方案了,因為環中不能移動
? 所以我們直接並查集判斷一下統計一下就好了
?
?? 代碼大概長這個樣子
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=1e5+10,MOD=1e9+7; int f[N*2],in[N*2],cnt[N*2],mark[N*2]; int n,m,tot,ans; int get_f(int x){return f[x]=f[x]==x?f[x]:get_f(f[x]);} int mul(int x,int y){return 1LL*x*y%MOD;} int main(){ #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); #endif int x,y; scanf("%d",&n); for (int i=1;i<=2*n;++i) f[i]=i,cnt[i]=1,mark[i]=0; ans=1; int tmp=0; for (int i=1;i<=n;++i){ scanf("%d%d",&x,&y); get_f(x); get_f(y); mark[x]=1; tmp=max(tmp,max(x,y)); if (x==y) continue; if (f[x]==f[y]) ans=mul(ans,2); cnt[f[y]]+=cnt[f[x]]; f[f[x]]=f[y]; } int debug=0; for (int i=1;i<=2*n;++i) if (!mark[i]) ans=mul(ans,cnt[i]),++debug; printf("%d\n",ans); }
【cf859E】Desk Disorder