bzoj 1997[Hnoi2010]Planar - 2-SAT

1997: [Hnoi2010]Planar

Time Limit: 10 Sec  Memory Limit: 64 MB

Description

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

Sample Output

NO
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\n");
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\n");
168         } else {
169             printf("NO\n");
170         }
171     }
172 }
View Code

 

posted @ 2018-03-28 22:21  大财主  阅读(215)  评论(2编辑  收藏  举报