NEERC天天被搬还是做了好了。
Abbreviation
模拟。
#define FIO "abbreviation"
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 500005;
int n, p[MAXN];
string t[MAXN];
char s[MAXN];
inline bool In(int x, int l, int r)
{
return x >= l && x <= r;
}
inline int Find(int x)
{
if (!In(s[x], 'A', 'Z') || !In(s[x + 1], 'a', 'z'))
return 0;
for (x ++; In(s[x], 'a', 'z'); x ++);
if (In(s[x], 'A', 'Z'))
return 0;
return x;
}
inline int Chk(int x)
{
int y, z;
if (!(y = Find(x)) || s[y] != ' ' || !(z = Find(y + 1)))
return 0;
t[x] += s[x], t[x] += s[y + 1];
while (true)
{
if (s[z] != ' ' || !(y = Find(z + 1)))
return z - 1;
t[x] += s[z + 1];
z = y;
}
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#else
freopen(FIO".in", "r", stdin);
freopen(FIO".out", "w", stdout);
#endif
for (char c = getchar(); ~c; c = getchar())
s[++ n] = c;
for (int i = 1, j; i <= n; i ++)
if (!In(s[i - 1], 'A', 'Z') && !In(s[i - 1], 'a', 'z'))
if (j = Chk(i))
p[i] = 1, p[j] = 2, i = j;
for (int i = 1; i <= n; i ++)
{
if (p[i] == 1)
printf("%s (", t[i].c_str());
putchar(s[i]);
if (p[i] == 2)
putchar(')');
}
}
Binary Code
暴力是枚举两个点的两种状态,看是否一个是另一个的前缀,跑2-SAT。
考虑用trie树优化建边,分别是前缀和和后缀和(表示选没选)。
#define FIO "binary"
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 1000005;
const int MAXM = 4000005;
int n, tot, len, cnt, num, scc[MAXM], par[MAXN], pos[MAXN], st[MAXN], ed[MAXN], tst[MAXN], ted[MAXN], dfn[MAXM], nxt[MAXN][2];
vector <int> adj[MAXM], vec[MAXN], G[MAXM];
char s[MAXN], ch[MAXN];
bool res[MAXN];
inline void Add(int p)
{
int cur = 0;
for (int i = 1; i <= len; cur = nxt[cur][s[i ++] - '0'])
if (!nxt[cur][s[i] - '0'])
par[nxt[cur][s[i] - '0'] = ++ cnt] = cur;
pos[p] = cur;
vec[cur].pb(p);
}
inline void Build()
{
for (int i = 1; i <= cnt; i ++)
if (!vec[i].empty())
{
for (int j = 0; j < vec[i].size(); j ++)
if (!j)
adj[++ tot].pb(vec[i][j] ^ 1);
else
adj[vec[i][j]].pb(tot), adj[tot + 1].pb(tot), adj[++ tot].pb(vec[i][j] ^ 1);
tst[i] = tot;
for (int j = 0; j < vec[i].size(); j ++)
if (!j)
adj[vec[i][j]].pb(++ tot);
else
adj[tot].pb(vec[i][j] ^ 1), adj[tot].pb(tot + 1), adj[vec[i][j]].pb(++ tot);
ted[i] = tot;
}
for (int i = 2; i <= (n << 1 | 1); i ++)
for (int j = par[pos[i]]; j; j = par[j])
if (!vec[j].empty())
adj[i].pb(tst[j]), adj[ted[j]].pb(i ^ 1);
}
int sta[MAXM], low[MAXM], tim, tp;
inline void Dfs(int x)
{
dfn[x] = low[x] = ++ tim;
sta[++ tp] = x;
for (auto y : adj[x])
if (!dfn[y])
Dfs(y), low[x] = min(low[x], low[y]);
else if (!scc[y])
low[x] = min(low[x], dfn[y]);
if (dfn[x] == low[x])
{
int cur = 0; num ++;
while (cur ^ x)
scc[cur = sta[tp --]] = num;
}
}
int vis[MAXM], opp[MAXM], deg[MAXM], q[MAXM], ql, qr;
inline void Print()
{
for (int i = 1; i <= n; i ++)
opp[scc[i << 1]] = scc[i << 1 | 1], opp[scc[i << 1 | 1]] = scc[i << 1];
for (int x = 2; x <= tot; x ++)
for (auto y : adj[x])
if (scc[x] ^ scc[y])
G[scc[y]].pb(scc[x]), deg[scc[x]] ++;
for (int i = 1; i <= num; i ++)
if (!deg[i])
q[++ qr] = i;
while (ql ^ qr)
{
int x = q[++ ql];
if (!vis[x])
vis[x] = 1, vis[opp[x]] = -1;
for (auto y : G[x])
if (!-- deg[y])
q[++ qr] = y;
}
for (int i = 2; i <= (n << 1 | 1); i ++)
if (~vis[scc[i]])
res[i >> 1] = i & 1;
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#else
freopen(FIO".in", "r", stdin);
freopen(FIO".out", "w", stdout);
#endif
n = Read(), tot = n << 1 | 1;
for (int i = 1, t = 1; i <= n; i ++)
{
scanf("%s", s + 1), len = strlen(s + 1);
st[i] = t;
for (int j = 1; j <= len; j ++)
ch[t ++] = s[j];
ed[i] = t;
for (int j = 1; j <= len; j ++)
if (s[j] == '?')
{
s[j] = '0', Add(i << 1);
s[j] = '1', Add(i << 1 | 1);
break;
}
else if (j == len)
Add(i << 1), Add(i << 1 | 1);
}
Build();
for (int i = 2; i <= tot; i ++)
if (!dfn[i])
Dfs(i);
for (int i = 1; i <= n; i ++)
if (scc[i << 1] == scc[i << 1 | 1])
return puts("NO"), 0;
puts("YES");
Print();
for (int i = 1; i <= n; putchar(10), i ++)
for (int j = st[i]; j < ed[i]; j ++)
if (ch[j] == '?')
putchar(res[i] + '0');
else
putchar(ch[j]);
return 0;
}
Cactus Construction
先把所有环和桥边分开,然后随便构造一下就好了。
详见代码。
#define FIO "cactus"
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 50005;
struct Node
{
int opt, a, b, c;
Node(int _opt = 0, int _a = 0, int _b = 0, int _c = 0)
{
opt = _opt, a = _a, b = _b, c = _c;
}
};
int n, m, tim, cnt, par[MAXN], a[MAXN], dfn[MAXN];
vector <int> adj[MAXN], hav[MAXN], cir[MAXN];
vector <Node> ans;
bool f[MAXN];
inline void Dfs(int x)
{
dfn[x] = ++ tim;
for (auto y : adj[x])
if (y ^ par[x])
if (!dfn[y])
par[y] = x, Dfs(y);
else if (dfn[y] < dfn[x])
{
hav[y].pb(++ cnt);
cir[cnt].pb(y);