1997: [Hnoi2010]Planar
Time Limit: 10 Sec Memory Limit: 64 MBDescription
Input
Output
Sample Input
2
6 9
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6
1 4 2 5 3 6
5 5
1 2
2 3
3 4
4 5
5 1
1 2 3 4 5
6 9
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6
1 4 2 5 3 6
5 5
1 2
2 3
3 4
4 5
5 1
1 2 3 4 5
Sample Output
NO
YES
YES
先根据平面图的性质, e <= 3 * v - 6, e过大直接就判负了,这样边数是 N^2级别的
按照2-SAT的建图方法,分为边在环里和边在环外,如果两边在环里相交,就只能一内一外
所以如果 e[i] 和 e[j] 会在环内相交的话 i -> j'' , j'' -> i , i'' -> j , j->i'' 分别连边
然后tarjan 跑强连通,因为这题不用输出方案数,只需要判断 i 和 i'' 是不是在一个强连通分量里就可以了
判断在环内相交 就是 e[i].u < e[j].u && e[j].u < e[i].v && e[i].v < e[j].v
这个自己画一画就明白了。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define LL long long 6 7 using namespace std; 8 9 const int MAXN = 4e2 + 10; 10 int T, N, M; 11 12 int in[MAXN][MAXN]; 13 int cir[MAXN]; 14 int col[MAXN * MAXN]; 15 int head[MAXN * MAXN]; 16 int ra[MAXN]; 17 int sta[MAXN * MAXN]; 18 int vis[MAXN * MAXN], low[MAXN * MAXN], dfn[MAXN * MAXN]; 19 int top = 0; 20 int cnt = 0, tot = 0; 21 struct edge { 22 int u, v; 23 int next; 24 } e[MAXN * MAXN * 4], g[MAXN * MAXN * 4], E[MAXN * MAXN * 4]; 25 26 inline LL read() 27 { 28 LL x = 0, w = 1; char ch = 0; 29 while(ch < '0' || ch > '9') { 30 if(ch == '-') { 31 w = -1; 32 } 33 ch = getchar(); 34 } 35 while(ch >= '0' && ch <= '9') { 36 x = x * 10 + ch - '0'; 37 ch = getchar(); 38 } 39 return x * w; 40 } 41 42 void DFS(int x) 43 { 44 vis[x] = 1; 45 low[x] = dfn[x] = ++tot; 46 sta[top++] = x; 47 for(int j = head[x]; j; j = g[j].next) { 48 int to = g[j].v; 49 if(!vis[to]) { 50 DFS(to); 51 low[x] = min(low[x], low[to]); 52 } else if(vis[to] == 1) { 53 low[x] = min(low[x], dfn[to]); 54 } 55 } 56 if(dfn[x] == low[x]) { 57 ++cnt; 58 while(sta[top - 1] != x) { 59 col[sta[top - 1]] = cnt; 60 vis[sta[top - 1]] = 2; 61 top--; 62 } 63 col[x] = cnt; 64 vis[x] = 2; 65 top--; 66 } 67 } 68 69 bool check() 70 { 71 for(int i = 1; i <= 2 * M; i++) { 72 if(!vis[i]) { 73 DFS(i); 74 } 75 } 76 for(int i = 1; i <= M; i++) { 77 if(col[i] == col[i + M]) { 78 return false; 79 } 80 } 81 return true; 82 } 83 84 void addedge(int u, int v) 85 { 86 g[++cnt].next = head[u]; 87 g[cnt].v = v; 88 head[u] = cnt; 89 } 90 91 int main() 92 { 93 // freopen("input3.in", "r", stdin); 94 // freopen("t.out", "w", stdout); 95 T = read(); 96 while(T--) { 97 memset(vis, 0, sizeof vis); 98 memset(low, 0, sizeof low); 99 memset(col, 0, sizeof col); 100 memset(dfn, 0, sizeof dfn); 101 memset(head, 0, sizeof head); 102 memset(in, 0, sizeof in); 103 memset(cir, 0 , sizeof cir); 104 memset(ra, 0, sizeof ra); 105 N = read(), M = read(); 106 tot = 0; 107 for(int i = 1; i <= M; i++) { 108 e[i].u = read(), e[i].v = read(); 109 } 110 for(int i = 1; i <= N; i++) { 111 int num = read(); 112 ra[num] = i; 113 cir[i] = num; 114 } 115 if(M > 3 * N + 6) { 116 printf("NO "); 117 continue; 118 } 119 /*if(T == 1) { 120 cout<<N<<" "<< 121 for(int i = 1; i <= N; i++) 122 cout<<cir[i]<<" "; 123 cout<<endl<<endl; 124 }*/ 125 for(int i = 1; i <= N; i++) { 126 in[cir[i]][cir[i % N + 1]] = in[cir[i % N + 1]][cir[i]] = 1; 127 } 128 for(int i = 1; i <= M; i++) { 129 if(in[e[i].u][e[i].v] == 1) { 130 continue; 131 } 132 if(ra[e[i].u] > ra[e[i].v]) { 133 swap(e[i].u, e[i].v); 134 } 135 E[++tot].u = e[i].u, E[tot].v = e[i].v; 136 } 137 M = tot; 138 cnt = 0; 139 /* if(T == 1) { 140 cout<<endl; 141 for(int i = 1; i <= M; i++) { 142 cout<<E[i].u<<" "<<E[i].v<<" "<<ra[E[i].u]<<" "<<ra[E[i].v]<<endl; 143 } 144 cout<<endl; 145 }*/ 146 for(int i = 1; i < M; i++) { 147 for(int j = i + 1; j <= M; j++) { 148 int u = ra[E[i].u], v = ra[E[i].v], x = ra[E[j].u], y = ra[E[j].v]; 149 if((u < x && x < v && v < y) || (u > x && y > u && v > y)) { 150 addedge(i, j + M); 151 addedge(i + M, j); 152 addedge(j, i + M); 153 addedge(j + M, i); 154 } 155 } 156 } 157 /* for(int i = 1; i <= M; i++) { 158 cout<<i<<endl; 159 for(int j = head[i]; j; j = g[j].next) { 160 int to = g[j].v; 161 cout<<to<<" "; 162 } 163 cout<<endl<<endl; 164 }*/ 165 tot = 0, cnt = 0; 166 if(check()) { 167 printf("YES "); 168 } else { 169 printf("NO "); 170 } 171 } 172 }