题目大意:
【问题背景】
高三的学长们就要离开学校,各奔东西了。某班n人在举行最后的离别晚餐时,饭店老板觉得十分纠结。因为有m名学生偷偷找他,要求和自己暗恋的同学坐在一起。
【问题描述】
饭店给这些同学提供了一个很长的桌子,除了两头的同学,每一个同学都与两个同学相邻(即坐成一排)。给出所有信息,满足所有人的要求,求安排的方案总数(这个数字可能很大,请输出方案总数取余989381的值,也可能为0)。
可以发现对于每个联通块只有两种排列方式,
对于每个联通快之间,可以用全排列。
然后就乱搞一下。。。
感觉基佬紫好像还挺好看的(滑稽)
今天是开始停课的-1天,希望noip rp++
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define mod 989381
using namespace std;
const int N=500100;
int n,m;
struct node{
int x,y,next;
}sa[N*2];int len=1,first[N];
int ss[N];
void ins(int x,int y)
{
len++;
sa[len].x=x;
sa[len].y=y;
sa[len].next=first[x];
first[x]=len;
}
int cnt=0;
bool tf[N],flag,ou;
map<int,int>f[N];
void dfs(int x,int fa)
{
tf[x]=1;
if(flag==1) return;
for(int i=first[x];i!=-1;i=sa[i].next)
{
int y=sa[i].y;
if(y!=fa)
{
if(tf[y]==1) flag=1;
else ou=1,dfs(y,x);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(first,-1,sizeof(first));
memset(ss,0,sizeof(ss));
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
if(x>y) swap(x,y);
if(!f[x][y])
{
ss[x]++;ss[y]++;
ins(x,y);ins(y,x);
f[x][y]=1;
}
}
for(int i=1;i<=n;i++)
{
if(ss[i]>2)
{
printf("0\n");
return 0;
}
}long long ans=1;
for(int i=1;i<=n;i++)
{
if(!tf[i])
{
flag=0;ou=0;
dfs(i,0);
if(flag==1)
{
printf("0\n");
return 0;
}
cnt++;
if(ou)ans=(ans*2)%mod;
}
}
for(int i=1;i<=cnt;i++) ans=(long long)(ans*i)%mod;
printf("%lld\n",ans);
}