poj3678:http://poj.org/problem?id=3678
题意:给你一些数,然后这些要么是0要么是1,然后回给出一些数之间的and,or,xor的值,问你是否存在一组解。
题解:2-sat的一道很好的题目。能很好训练建边的思想。建边如下。
and==1: 说明 a,b必须选,就是必须都是1,所以a->~a,b->~b;
ans==0,说明 a,b不能同时都选,那么选择了~a就只能选择b,选择了~b就只能选择a;所以有边,~a-->b,~b->a;
or==1说明至少有一个是1 ,至少取一个,a-->~b;b-->~a;
or==0说明都不取, ~a->a;~b->b;
xor==1建边 x->~y,y->~x,~y->x,~x->y (两个数必须不同)
xor==0 建边 x->y,y->x,~x->~y,~y->~x (两个数必须相同)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 const int N=1e5+10; 7 const int M=1e7+100; 8 struct Edge{ 9 int to,next; 10 } edge[M]; 11 int n,m,cnt,dep,top,atype; 12 int dfn[N],low[N],vis[N],head[N],st[N],belong[N],in[N],out[N],sum[N]; 13 //sum[i]记录第i个连通图的点的个数,in[i],out[i],表示缩点之后点的入度和初度。 14 void init(){ 15 cnt=dep=top=atype=0; 16 memset(head,-1,sizeof(head)); 17 memset(dfn,0,sizeof(dfn)); 18 memset(low,0,sizeof(low)); 19 memset(vis,0,sizeof(vis)); 20 memset(belong,0,sizeof(belong)); 21 memset(in,0,sizeof(in)); 22 memset(out,0,sizeof(out)); 23 memset(sum,0,sizeof(sum)); 24 } 25 void addedge(int u,int v){ 26 edge[cnt].to=v; 27 edge[cnt].next=head[u]; 28 head[u]=cnt++; 29 } 30 31 void Tarjan(int u){ 32 dfn[u]=low[u]=++dep; 33 st[top++]=u; 34 vis[u]=1; 35 for(int i=head[u]; i!=-1; i=edge[i].next){ 36 int v=edge[i].to; 37 if(!dfn[v]){ 38 Tarjan(v); 39 low[u]=min(low[u],low[v]); 40 } 41 else if(vis[v]){ 42 low[u]=min(low[u],dfn[v]); 43 } 44 } 45 int j; 46 if(dfn[u]==low[u]){ 47 atype++; 48 do{ 49 j=st[--top]; 50 belong[j]=atype; 51 sum[atype]++; //记录每个连通分量中点的个数 52 vis[j]=0; 53 } 54 while(u!=j); 55 } 56 } 57 char str[23]; 58 int u,v,w; 59 int main(){ 60 while(~scanf("%d%d",&n,&m)){ 61 init(); 62 for(int i=1;i<=m;i++){ 63 scanf("%d%d%d%s",&u,&v,&w,str); 64 u++;v++; 65 if(str[0]==‘A‘){ 66 if(w==1){ 67 addedge(u,u+n); 68 addedge(v,v+n); 69 } 70 else{ 71 addedge(u+n,v); 72 addedge(v+n,u); 73 } 74 } 75 else if(str[0]==‘O‘){ 76 if(w==1){ 77 addedge(u,v+n); 78 addedge(v,u+n); 79 } 80 else { 81 addedge(u+n,u); 82 addedge(v+n,v); 83 } 84 } 85 else if(str[0]==‘X‘){ 86 if(w==1){ 87 addedge(u,v+n); 88 addedge(u+n,v); 89 addedge(v+n,u); 90 addedge(v,u+n); 91 } 92 else{ 93 addedge(u,v); 94 addedge(v,u); 95 addedge(u+n,v+n); 96 addedge(v+n,u+n); 97 } 98 } 99 } 100 for(int i=1;i<=2*n;i++) 101 if(!dfn[i])Tarjan(i); 102 bool flag=false; 103 for(int i=1;i<=n;i++){ 104 if(belong[i]==belong[i+n]){ 105 flag=true; 106 break; 107 } 108 } 109 if(flag)printf("NO\n"); 110 else 111 printf("YES\n"); 112 } 113 }
时间: 2024-10-13 14:51:38