[BZOJ1997] [Hnoi2010]Planar - 2-SAT
1997: [Hnoi2010]Planar
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2639 Solved: 1015
[Submit][Status][Discuss]
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
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
HINT
题解:
2—SAT裸题...
如果两条边i,j有相交,那么我们创造一个命题"如果i则~j",逆否命题"如果j则~i",然后裸了...
Code:
#include <iostream> #include <cstdio> #include <vector> #include <cstring> using namespace std; int T, n, m; int L[10010], R[10010], num; struct edge{ int nxt,to; }ed[1000005]; int head[5005], cnt = 1; inline void add(int x, int y){ed[++cnt]=(edge){head[x],y};head[x]=cnt;} int dfn[5005], low[5005], dfnn; int stack[5005], top, C[5005], scc; bool ins[5005]; int pos[5005], D[5005]; void Tarjan(int x) { dfn[x] = low[x] = ++dfnn; stack[++top] = x, ins[x] = 1; for (register int i = head[x] ; i ; i = ed[i].nxt) { int to = ed[i].to; if (!dfn[to]){Tarjan(to);low[x]=min(low[x],low[to]);} else if(ins[to]) low[x] = min(low[x], low[to]); } if (dfn[x] == low[x]) { scc++;int y; do{ y = stack[top--], ins[y] = 0; C[y] = scc; }while(y != x); } } inline void init() { cnt=1;top=0;dfnn=0;num=0;scc=0; memset(ins, 0, sizeof ins); memset(C, 0, sizeof C); memset(head, 0, sizeof head); memset(stack, 0, sizeof stack); memset(pos, 0, sizeof pos); memset(dfn, 0, sizeof dfn); memset(low, 0, sizeof low); memset(D, 0, sizeof D); // cleann(ins, 0), cleann(C, 0), cleann(head, 0), cleann(stack, 0); // cleann(pos, 0), cleann(dfn, 0), cleann(low, 0),cleann(D, 0); } int main() { scanf("%d", &T); while (T--) { init(); scanf("%d%d", &n, &m); for (register int i = 1 ; i <= m ; i ++) scanf("%d%d", &L[i], &R[i]); for (register int i = 1 ; i <= n ; i ++) scanf("%d", &D[i]); if (m > 3 * n - 6) {puts("NO");continue;} for (register int i = 1 ; i <= n ; i ++) pos[D[i]] = i; for (register int i = 1 ; i <= m ; i ++) { R[i] = pos[R[i]], L[i] = pos[L[i]]; if (R[i] < L[i]) swap(R[i], L[i]);//R[i] > L[i] if (R[i] - L[i] == 1 or (R[i] == n and L[i] == 1)) continue; L[++num] = L[i], R[num] = R[i]; } for (register int i = 1 ; i <= num ; i ++) { for (register int j = 1 ; j <= num ; j ++) { if (i == j) continue; if ((L[i] > L[j] and R[j] > L[i] and R[j] < R[i]) or (L[i] < L[j] and R[j] > R[i] and R[i] > L[j])) { add(i , j + num); add(j + num, i); } } } for (register int i = 1 ; i <= 2 * num ; i ++) if (!dfn[i]) Tarjan(i); bool flag = 0; for (register int i = 1 ; i <= num ; i ++) { if (C[i] == C[i + num]) {puts("NO");flag = 1;break;} } if (!flag)puts("YES"); } }