Blog of RuSun

\begin {array}{c} \mathfrak {One Problem Is Difficult} \\\\ \mathfrak {Because You Don't Know} \\\\ \mathfrak {Why It Is Diffucult} \end {array}

P2444 [POI2000]病毒

P2444 [POI2000]病毒

建 AC 自动机,需要找到一个环并且永远不接触到病毒的终点位置。建 AC 自动机后,原来 Trie 树上的边已经被压缩过了,可以直接使用。有向图找环不能写假了。

查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
template <class Type>
void read (Type &x)
{
char c;
bool flag = false;
while ((c = getchar()) < '0' || c > '9')
if (c == '-') flag = true;
x = c - '0';
while ((c = getchar()) >= '0' && c <= '9')
x = (x << 3) + (x << 1) + c - '0';
if (flag) x = ~x + 1;
}
template <class Type, class ...Rest>
void read (Type &x, Rest &...y) { read(x), read(y...); }
template <class Type>
void write (Type x)
{
if (x < 0) putchar('-'), x = ~x + 1;
if (x > 9) write(x / 10);
putchar('0' + x % 10);
}
const int N = 3e4 + 10;
int tot;
char str[N];
struct Node { bool ed; int vis, p, s[2]; } tr[N];
void insert ()
{
scanf("%s", str + 1);
int n = strlen(str + 1), p = 0;
for (int i = 1; i <= n; ++i)
{
int &s = tr[p].s[str[i] - '0'];
if (!s) s = ++tot;
p = s;
}
tr[p].ed = true;
}
void build ()
{
queue <int> q;
for (int i = 0; i < 2; ++i)
if (tr[0].s[i]) q.push(tr[0].s[i]);
while (!q.empty())
{
int p = q.front(); q.pop();
for (int i = 0; i < 2; ++i)
{
int &s = tr[p].s[i];
if (!s) s = tr[tr[p].p].s[i];
else
{
q.push(s);
tr[s].p = tr[tr[p].p].s[i];
tr[s].ed |= tr[tr[s].p].ed;
}
}
}
}
bool dfs (int u)
{
if (tr[u].vis == 1) return true;
if (tr[u].vis == -1) return false;
tr[u].vis = 1;
for (int i = 0; i < 2; ++i)
if (!tr[tr[u].s[i]].ed && dfs(tr[u].s[i]))
return true;
tr[u].vis = -1;
return false;
}
int main ()
{
int T; read(T);
while (T--) insert();
build();
puts(dfs(0) ? "TAK" : "NIE");
return 0;
}