[BZOJ1997][Hnoi2010]Planar 2-sat (联通分量) 平面图
1997: [Hnoi2010]Planar
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2317 Solved: 850
[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
Source
太强辣。
平面图的边数不大于3*n-6剪枝。
先将环提出来,对于剩下的边,我们可以选择在环外连还是在环内连。
对于不相交的边,显然在环外连和在环内连都不会相交。
对于相交的边,显然不能同时在环外连或在环内连。只能一个在环外一个在环内。
将一条边拆为环外、环内两条边,构造2-sat。
判断2*i和2*i-1是否在同一个联通分量里。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #define LL long long 9 #define mod 19650827 10 using namespace std; 11 int read() { 12 char ch=getchar();int x=0,f=1; 13 while(!isdigit(ch)){ch=getchar();} 14 while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} 15 return x; 16 } 17 int T; 18 int n,m; 19 struct data { 20 int u,v; 21 }a[10005]; 22 int pos[10005]; 23 int cnt=0; 24 int head[10005],cntt; 25 struct edge { 26 int to,next; 27 }e[1000002]; 28 void add(int u,int v) {e[cntt].to=v;e[cntt].next=head[u];head[u]=cntt++;} 29 int dfn[10005],low[10005],inq[10005],sz; 30 int sta[10005],top,bl[10005],scc; 31 void tarjan(int now) { 32 dfn[now]=low[now]=++sz; 33 sta[++top]=now;inq[now]=1; 34 for(int i=head[now];i>=0;i=e[i].next) { 35 int to=e[i].to; 36 if(!dfn[to]) {tarjan(to);low[now]=min(low[now],low[to]);} 37 else if(inq[to]) {low[now]=min(low[now],dfn[to]);} 38 } 39 if(low[now]==dfn[now]) { 40 int x=-1; 41 scc++; 42 while(x!=now) { 43 x=sta[top--];inq[x]=0; 44 bl[x]=scc; 45 } 46 } 47 } 48 int main() { 49 T=read(); 50 while(T--) { 51 cnt=0;cntt=0;top=0;scc=0;sz=0; 52 memset(head,-1,sizeof(head)); 53 memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low)); 54 memset(inq,0,sizeof(inq)); 55 n=read(),m=read(); 56 for(int i=1;i<=m;i++) a[i].u=read(),a[i].v=read(); 57 for(int i=1;i<=n;i++) pos[read()]=i; 58 if(m>3*n-6){printf("NO\n");continue;} 59 for(int i=1;i<=m;i++) { 60 int c=abs(pos[a[i].u]-pos[a[i].v]); 61 if(c==1||(max(pos[a[i].u],pos[a[i].v])==n&&min(pos[a[i].u],pos[a[i].v])==1)) continue; 62 a[++cnt]=a[i]; 63 } 64 for(int i=1;i<=cnt;i++) { 65 for(int j=i+1;j<=cnt;j++) { 66 int t1=pos[a[i].u],t2=pos[a[i].v]; 67 if(t1>t2) swap(t1,t2); 68 int t3=pos[a[j].u],t4=pos[a[j].v]; 69 if(t3>t4) swap(t3,t4); 70 if((t1<t3&&t2<t4&&t2>t3)||(t1>t3&&t2>t4&&t1<t4)) { 71 add(2*i-1,2*j);add(2*j,2*i-1); 72 add(2*i,2*j-1);add(2*j-1,2*i); 73 } 74 } 75 } 76 for(int i=1;i<=2*cnt;i++) if(!dfn[i]) tarjan(i); 77 bool flag=1; 78 for(int i=1;i<=cnt;i++) if(bl[2*i]==bl[2*i-1]){printf("NO\n");flag=0;break;} 79 if(flag)printf("YES\n"); 80 } 81 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~