noip之前学的内容了,看到题竟然忘了怎么建图了,复习一下。
2-sat
大概是对于每个元素,它有0和1两种选择,必须选一个但不能同时选。这之间又有一些二元关系,比如x&y=1等等。。。
先把每个点拆成0和1两个点。
那么我们就建图,如果x等于A的话y必须等于B,那么从x的A点向y的B点连一条有向边,表示选了一个点它所有的后继点也必须选。
没有一组合法解的情况当且仅当x的01两个点缩点后在同一个强联通分量里。
bzoj 1823
裸题
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define N 205 6 #define M 4005 7 using namespace std; 8 int n,m; 9 int head[N],ver[M],nxt[M],tot; 10 void add(int a,int b) 11 { 12 tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;return ; 13 } 14 int dfn[N],low[N],tim,in[N],st[N],top,cnt,be[N]; 15 void dfs(int x) 16 { 17 dfn[x]=low[x]=++tim; 18 st[++top]=x; 19 in[x]=1; 20 for(int i=head[x];i;i=nxt[i]) 21 { 22 if(!dfn[ver[i]]) 23 { 24 dfs(ver[i]); 25 low[x]=min(low[x],low[ver[i]]); 26 } 27 else if(in[ver[i]]) 28 { 29 low[x]=min(low[x],dfn[ver[i]]); 30 } 31 } 32 if(low[x]==dfn[x]) 33 { 34 cnt++;int y; 35 do 36 { 37 y=st[top--]; 38 be[y]=cnt; 39 in[y]=0; 40 }while(y!=x); 41 } 42 return ; 43 } 44 int main() 45 { 46 int cas; 47 scanf("%d",&cas); 48 while(cas--) 49 { 50 tim=tot=cnt=top=0; 51 memset(be,0,sizeof(be)); 52 memset(head,0,sizeof(head)); 53 memset(dfn,0,sizeof(dfn)); 54 memset(low,0,sizeof(low)); 55 scanf("%d%d",&n,&m); 56 char s1[10],s2[10]; 57 for(int i=1;i<=m;i++) 58 { 59 scanf("%s%s",s1,s2); 60 int k1,k2;k1=k2=0; 61 int len1=strlen(s1); 62 for(int i=1;i<len1;i++) 63 { 64 k1=k1*10+s1[i]-'0'; 65 } 66 int len2=strlen(s2); 67 for(int i=1;i<len2;i++) 68 { 69 k2=k2*10+s2[i]-'0'; 70 } 71 int op1,op2; 72 if(s1[0]=='m')op1=1;else op1=0; 73 if(s2[0]=='m')op2=1;else op2=0; 74 add(k1+(op1^1)*n,k2+op2*n); 75 add(k2+(op2^1)*n,k1+op1*n); 76 } 77 for(int i=1;i<=2*n;i++)if(!dfn[i])dfs(i); 78 bool flag=0; 79 for(int i=1;i<=n;i++)if(be[i]==be[i+n])flag=1; 80 if(flag)puts("BAD"); 81 else puts("GOOD"); 82 } 83 return 0; 84 }