1997: [Hnoi2010]Planar
1997: [Hnoi2010]Planar
分析:
首先在给定的那个环上考虑进行操作,如果环内有有两条边相交,那么可以把其中的一条放到环的外面去。所以转换为2-sat问题。
像这样,由于1-4和2-3在环内相交了,所以可以把1-4放到环外,就变成了下图。
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; } const int N = 1205; struct Edge{ int to, nxt; } e[2000005]; int head[N], dfn[N], low[N], bel[N], sk[N], c[N], pos[N], top, Index, tot, En; bool vis[N]; pair<int,int> g[10005]; inline void add_edge(int u,int v) { ++En; e[En].to = v, e[En].nxt = head[u]; head[u] = En; } void tarjan(int u) { low[u] = dfn[u] = ++Index; sk[++top] = u; vis[u] = 1; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (!dfn[v]) { tarjan(v); low[u] = min(low[u], low[v]); } if (vis[v]) low[u] = min(low[u], dfn[v]); } if (low[u] == dfn[u]) { ++tot; do { vis[sk[top]] = 0; bel[sk[top]] = tot; top --; } while (sk[top + 1] != u); } } bool judge(int a,int b,int c,int d) { if (b > c && b < d && a < c) return 1; if (a > c && a < d && b > d) return 1; return 0; } void solve() { int n = read(), m = read(), cnt = 0; for (int i = 1; i <= m; ++i) g[i].first = read(), g[i].second = read(); for (int i = 1; i <= n; ++i) c[i] = read(); if (m > 3 * n - 6) { puts("NO"); return ; } for (int i = 1; i <= n; ++i) pos[c[i]] = i; for (int i = 1; i <= m; ++i) { g[i].first = pos[g[i].first], g[i].second = pos[g[i].second]; if (g[i].first > g[i].second) swap(g[i].first, g[i].second); if (g[i].second - g[i].first == 1 || (g[i].first == 1 && g[i].second == n)) continue; g[++cnt] = g[i]; } m = cnt; for (int i = 1; i <= m; ++i) for (int j = i + 1; j <= m; ++j) { if (judge(g[i].first, g[i].second, g[j].first, g[j].second)) { add_edge(i, j + m); add_edge(i + m, j); add_edge(j, i + m); add_edge(j + m, i); } } for (int i = 1; i <= m + m; ++i) if (!dfn[i]) tarjan(i); bool flag = 1; for (int i = 1; i <= m; ++i) if (bel[i] == bel[i + m]) flag = 0; puts(flag ? "YES" : "NO"); top = Index = En = tot = 0; for (int i = 0; i <= m + m; ++i) head[i] = dfn[i] = low[i] = bel[i] = 0; } int main() { for (int T = read(); T--; ) solve(); return 0; }