3444: 最后的晚餐

3444: 最后的晚餐

https://www.lydsy.com/JudgeOnline/problem.php?id=3444

分析:

  计数。

  首先判断无解的情况,因为这是一张长桌子,所以出现了环无解,然后并查集判环。如果是两个人之间的环,可以跳过。因为每个人只能和两个人挨着,所以三个及三个以上都想和一个人挨着,那么无解。

  然后就成了很多条序列,往一个大的序列上放,那么全排列为$A^n_n$,即n!。对于每个序列,它又有两种方法排列,(长度为1的只有一种),然后再乘以2。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 
 5 inline int read() {
 6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
 7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
 8 }
 9 
10 const int mod = 989381;
11 const int N = 500100;
12 
13 int fa[N], du[N], cnt[N], L[N];
14 
15 int find(int x) {
16     return x == fa[x] ? x : fa[x] = find(fa[x]);
17 }
18 
19 int main() {
20     
21     int n = read(), m = read(), tot = 0;
22     for (int i=1; i<=n; ++i) fa[i] = i;
23     
24     for (int t1,t2,i=1; i<=m; ++i) {
25         int u = read(), v = read();
26         if (u == L[v]) continue;
27 
28         if ((t1=find(u)) == (t2=find(v)) || du[u] >= 2 || du[v] >= 2) {
29             puts("0");return 0;
30         }
31         
32         L[u] = v;
33         du[u] ++, du[v] ++; // du[t1]++ , du[t2]++
34         fa[t1] = t2;
35     }
36     
37     LL ans = 1;
38     
39     for (int i=1; i<=n; ++i) cnt[find(i)] ++;
40     
41     for (int i=1; i<=n; ++i) {
42         if (cnt[i]) {
43             if (cnt[i] > 1) ans = (ans * 2) % mod;
44             tot ++;
45         }
46     }
47     
48     for (int i=1; i<=tot; ++i) ans = (ans * i) % mod;
49     
50     cout << ans;
51     
52     return 0;
53 }
原文地址:https://www.cnblogs.com/mjtcn/p/9349348.html