UVA11174 Stand in a Line
阿新 • • 發佈:2018-12-09
連結
題解
首先我建一個虛點,設其為森林中所有樹的父親,那現在就成一棵樹了 設為以節點為根的子樹的答案 那麼點本身肯定排在所有子節點的前面,現在只需考慮其子樹中的點怎麼排列,子樹內部先排列,然後再把這些排列交錯著插起來,子樹之間是獨立的,如果把同一棵子樹上的點看作相同的點,那麼這就是有重複元素的排列組合,假設子樹的大小為,那麼
其中程式碼
//數學題
#include <bits/stdc++.h>
#define maxn 100010
#define mod 1000000007ll
#define cl(x) memset(x,0,sizeof(x))
#define ll long long
using namespace std;
ll head[maxn], to[maxn], nex[maxn], etot, N, M, mark[maxn], sz[maxn], ans, inv[maxn];
void adde(ll a, ll b){to[++etot]=b;nex[etot]=head[a];head[a]=etot;}
ll read(ll x=0)
{
ll c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if (c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
return f*x;
}
void preprocess()
{
ll i;
inv[1]=1;
for(i=2;i<maxn;i++)inv[i]=inv[mod%i]*(mod-mod/i)%mod;
}
void init()
{
ll i, a, b;
cl(head), cl(nex), etot=0, cl(mark), cl(sz), ans=1;
N=read(), M=read();
for(i=1;i<=M;i++)a=read(), b=read(), adde(b,a), mark[a]=1;
for(i=1;i<=N;i++)if(!mark[i])adde(N+1,i);
}
void dfs(ll pos)
{
ll p;
sz[pos]=1;
for(p=head[pos];p;p=nex[p])
{
dfs(to[p]);
sz[pos]+=sz[to[p]];
}
if(pos!=N+1)ans=ans*inv[sz[pos]]%mod;
}
void show()
{
ll i;
for(i=1;i<=N;i++)ans=ans*i%mod;
printf("%lld\n",ans);
}
int main()
{
ll T=read();
preprocess();
while(T--)
{
init();
dfs(N+1);
show();
}
return 0;
}