【题意】
给定一个含哈密顿回路(回路将给出)的图。判断它是不是一个平面图。
【分析】
居然是2-SAT。
由于有一个哈密顿回路,我们先不管其它不在回路上的边,把这幅图围成一个媛。
接下来再考虑其它边。对于其中的任意两条边,如果它们不相交,则必定一个边在圆外,一个边在圆内。
而圆外与圆内是一对相对的状态,又由于状态的选取受其它状态的限制,所以考虑用2-SAT。将每一个不在回路上的边看做两个点i与i'。对于每一对相交的边,连无向边<i,j'>,<j,i'>(因为可以相互影响)。然后缩点判定即可。
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int mn = 205, mm = 10005;
struct edge{
int a, b;
}e[mm], E[mm];
vector<int > g[mm];
int cir[mn], pos[mn], n, m;
int dfn[mm], low[mm], times;
int stk[mm], scc[mm], cnt, top;
bool instk[mm];
inline void init()
{
for(int i = 0; i <= m; i++)
g[i].clear(), dfn[i] = low[i] = stk[i] = scc[i] = 0, instk[i] = 0;
times = cnt = top = 0;
}
inline int getint()
{
int ret = 0, flag = 1;
char c = getchar();
while(c == ' ' || c == '\n')
c = getchar();
if(c == '-')
flag = -1, c = getchar();
while(c >= '0' && c <= '9')
ret = ret * 10 + c - '0', c = getchar();
return ret * flag;
}
inline void addedge(int a, int b){g[a].push_back(b), g[b].push_back(a);}
void tarjan(int s)
{
dfn[s] = low[s] = ++times, stk[++top] = s, instk[s] = 1;
int siz = g[s].size();
for(int i = 0; i < siz; i++)
{
int t = g[s][i];
if(!dfn[t])
tarjan(t), low[s] = min(low[s], low[t]);
else if(instk[t])
low[s] = min(low[s], dfn[t]);
}
if(dfn[s] == low[s])
{
++cnt;
while(stk[top] != s)
instk[stk[top]] = 0, scc[stk[top]] = cnt, top--;
instk[stk[top]] = 0, scc[stk[top]] = cnt, top--;
}
}
inline bool check()
{
for(int i = 1; i <= m; i++)
if(scc[i] == scc[i + m])
return 0;
return 1;
}
int main()
{
int t = getint(), i, j;
while(t--)
{
n = getint(), m = getint();
for(i = 1; i <= m; i++)
e[i].a = getint(), e[i].b = getint();
for(i = 1; i <= n; i++)
scanf("%d", &cir[i]);
for(i = 1; i <= n; i++)
pos[cir[i]] = i;
if(m > 3 * n - 6)
{
puts("NO");
continue;
}
init();
for(i = 1; i <= m; i++)
{
e[i].a = pos[e[i].a], e[i].b = pos[e[i].b];
if(e[i].a > e[i].b)
swap(e[i].a, e[i].b);
if(e[i].b - e[i].a == 1 || e[i].b - e[i].a == n - 1)
continue;
E[++top] = e[i];
}
m = top, top = 0;
for(i = 1; i <= m; i++)
for(j = i + 1; j <= m; j++)
if((E[i].a < E[j].a && E[j].a < E[i].b && E[i].b < E[j].b) || (E[i].a > E[j].a && E[j].b > E[i].a && E[i].b > E[j].b))
addedge(i, j + m), addedge(i + m, j);
for(i = 1; i <= (m << 1); i++)
if(!dfn[i])
tarjan(i);
puts(check() ? "YES" : "NO");
}
}