BZOJ 3953 Self-Assembly 解题报告

首先,我们可以先考虑一个暴力一点的算法:

对于任意两个分子,如果它们能以至少一种进行匹配,那么我们就在这两个分子之间连一条边。

然后如果我们能找到一个环,就说明是 unbounded,否则就是 bounded。

复杂度是 $O(n^2)$ 的,然而 $n le 40000$ ,显然是不行的。

考虑优化。我们注意到本质不同的边有 $26$ 种,那么我们应该能省去很多不必要的边。

令 $inv(x)$ 为与类型为 $x$ 的离子匹配的离子,如 $inv(A+)=A-$。

对于在同一个分子上的两个离子 $x$ 和 $y$ ,连有向边 $x ightarrow inv(y)$ 和 $y ightarrow inv(x)$。

然后只要判断这个图是否有环即可。

然后这个图只有 $52$ 个点,不是想怎么搞就怎么搞嘛。。。

(感谢 HZC 的谆谆教诲)

毕竟 Gromah 太弱,再一次 WA 到死。

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 #define D 52 + 5
10 
11 int n;
12 int q[D];
13 bool Flag[D];
14 bool Map[D][D];
15 char s[9];
16 
17 inline int get(char ch_1, char ch_2)
18 {
19     if (ch_1 == '0') return -1;
20     return (ch_1 - 'A') << 1 | (ch_2 == '+');
21 }
22 
23 inline bool BFS(int S)
24 {
25     int l = 0, r = 0;
26     for (int i = 0; i < 52; i ++) Flag[i] = 0;
27     q[0] = S, Flag[S] = 1;
28     while (l <= r)
29     {
30         int z = q[l ++];
31         for (int d = 0; d < 52; d ++)
32         {
33             if (!Map[z][d]) continue ;
34             if (d == S) return 1;
35             if (Flag[d]) continue;
36             q[++ r] = d, Flag[d] = 1;
37         }
38     }
39     return 0;
40 }
41  
42 int main()
43 {
44     #ifndef ONLINE_JUDGE
45         freopen("3953.in", "r", stdin);
46         freopen("3953.out", "w", stdout);
47     #endif
48     
49     scanf("%d", &n);
50     for (int i = 0; i < n; i ++)
51     {
52         scanf("%s", s);
53         for (int j = 0; j < 6; j += 2)
54             for (int k = j + 2; k < 8; k += 2)
55             {
56                 int a = get(s[j], s[j + 1]), b = get(s[k], s[k + 1]);
57                 if ((!~a) || (!~b)) continue ;
58                 Map[a][b ^ 1] = 1;
59                 Map[b][a ^ 1] = 1;
60             }
61     }
62     bool ok = 0;
63     for (int i = 0; !ok && i < 52; i ++)
64         ok = BFS(i);
65     puts(ok ? "unbounded" : "bounded");
66     
67     #ifndef ONLINE_JUDGE
68         fclose(stdin);
69         fclose(stdout);
70     #endif
71     return 0;
72 }

 

原文地址:https://www.cnblogs.com/gromah/p/4426283.html