Feeling \ (2-SAT \) title with network flow a little bit like, are considering how to build map, then run the board
The \ (2-SAT \) a construction diagram thinking subject is transformed into a true a false format, then it is better to
Description
And to a map on a Hamilton circuit diagram, it is determined that it is not possible to convert a plan
\(n \leq 200\),\(m \leq 10000\)
Multiple sets of data ( \ (DOC \) I did not measure more than empty, \ (WA \) several hair)
Solution
First, a practical \ (Trick \) : plan view, \ (m \-Leq. 6 with 3N \)
The proof plan to learn when to say it
Hamilton put a loop thought of as a circle (polygon) on the plane
The point is not the way back chord on the circle (polygon diagonal), or even in outer ring
Two chords intersect conditions have to meet
for (int i = 1; i < m; ++i) {
for (int j = i + 1; j <= m; ++j) {
int p = id[ex[i]], q = id[ey[i]], r = id[ex[j]], s = id[ey[j]];
if (p > q)
swap(p, q);
if (r > s)
swap(r, s);
if ((p < r && q > r && q < s || (r < p && s > p && s < q)))
add(i, j + m), add(i + m, j), add(j, i + m), add(j + m, i);
}
}
Anyway, bloggers is to understand the (drawing can be emotional understanding)
Then run \ (tarjan \) is gone
Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm {
inline int read() {
int res = 0, f = 1;
char k;
while (!isdigit(k = getchar()))
if (k == '-')
f = -1;
while (isdigit(k)) res = res * 10 + k - '0', k = getchar();
return res * f;
}
const int N = 1e4 + 10;
int dfn[N], low[N], scc[N], st[N], tot, tim, top, u[N], v[N], c[N], ex[N], ey[N], now;
vector<int> g[N];
int n, id[N], m;
bool f[300][300], vis[N];
inline void add(int u, int v) { return g[u].push_back(v), void(); }
inline void tarjan(int x) {
dfn[x] = low[x] = ++tim;
vis[x] = 1;
st[++top] = x;
int sz = g[x].size();
for (int i = 0; i < sz; ++i) {
int t = g[x][i];
if (!dfn[t])
tarjan(t), low[x] = min(low[x], low[t]);
else if (vis[t])
low[x] = min(low[x], dfn[t]);
}
if (dfn[x] == low[x]) {
++tot;
while (st[top] != x) scc[st[top]] = tot, vis[st[top--]] = 0;
scc[st[top]] = tot, vis[st[top--]] = 0;
}
return;
}
#define cl(x) memset(x, 0, sizeof(x))
inline void prework() {
cl(dfn);
cl(scc);
cl(st);
cl(u);
cl(v);
cl(ex);
now = 0;
tim = 0;
tot = 0;
top = 0;
cl(ey);
cl(id);
cl(vis);
cl(f);
for (int i = 1; i < N; ++i) g[i].clear();
return;
}
inline void work() {
n = read();
m = read();
for (int i = 1; i <= m; ++i) {
u[i] = read();
v[i] = read();
if (u[i] > v[i])
swap(u[i], v[i]);
}
for (int i = 1, x, y; i <= n; ++i) {
c[i] = read();
id[c[i]] = i;
if (i > 1) {
x = c[i];
y = c[i - 1];
f[min(x, y)][max(x, y)] = 1;
}
}
if (m > 3 * n - 6)
return puts("NO"), void();
f[min(c[1], c[n])][max(c[1], c[n])] = 1;
for (int i = 1; i <= m; ++i) {
if (f[u[i]][v[i]])
continue;
ex[++now] = u[i], ey[now] = v[i];
}
//把非回路上的点找出来
m = now;
for (int i = 1; i < m; ++i) {
for (int j = i + 1; j <= m; ++j) {
int p = id[ex[i]], q = id[ey[i]], r = id[ex[j]], s = id[ey[j]];
if (p > q)
swap(p, q);
if (r > s)
swap(r, s);
if ((p < r && q > r && q < s || (r < p && s > p && s < q)))
add(i, j + m), add(i + m, j), add(j, i + m), add(j + m, i);
}
}
for (int i = 1; i <= m * 2; ++i)
if (!dfn[i])
tarjan(i);
for (int i = 1; i <= m; ++i)
if (scc[i] == scc[i + m])
return puts("NO"), void();
puts("YES");
return;
}
signed main() {
int T = read();
while (T--) prework(), work();
return 0;
}
} // namespace yspm
signed main() { return yspm::main(); }