题意: 有n个人在圆桌上吃饭,主人位置固定,给m个关系ki表示第i个人的旁边是第ki个人,问有多少种方式可以排列…
注:这是一个圆桌,所以要分左右两边的…
给你n个人和m个关系
并查集处理下每个联通块,对(全部联通块-1)(因为1号位固定)进行全排列
再对每个元素大于1的联通块进行ans*=2,因为他们可以调转顺序
最后还有个最蛋疼的就是
n==2输出1
//URAL 1962
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
using namespace std;
typedef long long LL;
#define MM(a,x) memset(a,x,sizeof(a));
//#define mp make_pair
#define pb push_back
#define x first
#define y second
int mod=1e9+7;
int f[200],w[200],sum[200],n,m;
void init()
{
for(int i=1;i<=n;i++)
w[i]=1,f[i]=i;
}
int findf(int x)
{
if(x==f[x])
return x;
else return findf(f[x]);
}
void mix(int a,int b)
{
a=findf(a);
b=findf(b);
w[a]=w[b]=w[a]+w[b];
f[a]=b;
}
bool mp[200][200];
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
//debug=1;
#endif // LOCAL
cin>>n>>m;
init();
bool flag=0;
for(int i=1;i<=m;i++)
{
int v;
scanf("%d",&v);
if(mp[v][i]||mp[i][v]) continue;
sum[v]++;
sum[i]++;
if(sum[v]>2||sum[i]>2) flag=1;
mp[i][v]=mp[v][i]=1;
if(findf(i)!=findf(v))
mix(i,v);
else
{
if(w[findf(i)]!=n) flag=1;
}
}
if(n==2) cout<<1<<endl;
else if(!n) cout<<0<<endl;
else {
if(!flag)
{
int cnt=0,ct=0;
for(int i=1;i<=n;i++)
{
if(f[i]==i)
{
if(w[i]>1) cnt++;
else ct++;
}
}
LL ans=1;
for(int i=1;i<=cnt+ct-1;i++)
ans=(ans*i)%mod;
if(w[findf(1)]==1)
{
;
}
else
{
ans=(ans*2)%mod;
cnt--;
}
for(int i=1;i<=cnt;i++)
{
ans=(ans*2)%mod;
}
cout<<ans<<endl;
}
else cout<<0<<endl;
}
return 0;
}