zoukankan      html  css  js  c++  java
  • POJ 3207/ POJ 3678 【2SAT】


    POJ 3207 Ikki's Story IV - Panda's Trick
    大意:已知圆上均匀分布着n个点,编号按逆时针数分别为0,1,2,。。。n-1
    由上述点够成m条边,这些边可分布于圆内或圆外,问这些边有没有可能不相交?

    分析:
    2-SAT
    1.构图:
       每条边可在圆内或圆外,对应于两个点,Ai,Ai'
    2.若边i与边j相交,
     a.若选择Ai边则必须选Aj'边,
     b.若选择Ai'边则必须选择Aj边,
     故对应于上图:
      建立边(Ai,Aj'),(Ai',Aj)
    3.若存在边i,有Ai,Ai'属于同一个强连通分量,则一定会相交

    View Code
    1 #include<stdio.h>
    2 #include<string.h>
    3  constint N =500+10;
    4 #include<vector>
    5  usingnamespace std;
    6 vector<int>edge[N*2];//正向边
    7 vector<int>iedge[N*2];//逆向边
    8 struct Link
    9 {
    10 int a,b;
    11 }link[N];
    12
    13 inline void addEdge(int s,int t)
    14 {
    15 edge[s].push_back(t);
    16 iedge[t].push_back(s);
    17 }
    18 //判断两线段是否相交
    19 inline bool isconnect(Link A,Link B)
    20 {
    21 if(A.a<B.a&&B.a<A.b&&A.b<B.b)
    22 returntrue;
    23 if(B.a<A.a&&A.a<B.b&&B.b<A.b)
    24 returntrue;
    25 returnfalse;
    26 }
    27
    28 bool visited[N*2];
    29 int color[N*2];//color[i]标记i点所属分量
    30 vector<int>stack;//记录拓扑排序时的栈
    31
    32 void dfs1(int p)//dfs1实际是在求拓扑图,拓扑排序后的信息逆序存于statck中
    33 {
    34 if(visited[p]==true)return;
    35 visited[p]=true;
    36 int sz = edge[p].size();
    37 int i;
    38 for(i=0;i<sz;i++)
    39 {
    40 if(!visited[edge[p][i]])
    41 dfs1(edge[p][i]);
    42 }
    43
    44 stack.push_back(p);
    45 }
    46
    47 void dfs2(int n,int group)
    48 {
    49 if(visited[n]==true)return;
    50 visited[n]=true;
    51 int i,sz = iedge[n].size();
    52 for(i=0;i<sz;i++)
    53 {
    54 if(!visited[iedge[n][i]])
    55 dfs2(iedge[n][i],group);
    56 }
    57 color[n]=group;
    58 }
    59 void two_SAT(int n)//n为点的个数
    60 {
    61 memset(visited,false,sizeof(visited));
    62 int i,j;
    63 stack.clear();
    64 for(i=0;i<n;i++)
    65 {
    66 if(!visited[i])dfs1(i);
    67 }
    68
    69 memset(visited,false,sizeof(visited));
    70
    71 int group =0;
    72 int sz = stack.size();
    73 for(i=sz-1;i>=0;i--)
    74 {
    75 if(!visited[i])
    76 dfs2(i,group++);
    77 }
    78
    79 }
    80
    81 //判断Ai,Ai'是否属于同一个强连通分量
    82 bool check(int m)
    83 {
    84 for(int i=0;i<m;i++)
    85 if(color[i]==color[i+m])returnfalse;
    86 returntrue;
    87 }
    88
    89 int main()
    90 {
    91 int n,m;
    92 while(scanf("%d%d",&n,&m)!=EOF)
    93 {
    94 int i,j;
    95 for(i=0;i<2*m+1;i++)
    96 {
    97 edge[i].clear();
    98 iedge[i].clear();
    99 }
    100 for(i=0;i<m;i++)
    101 {
    102 scanf("%d%d",&link[i].a,&link[i].b);
    103 if(link[i].a>link[i].b)
    104 {
    105 int temp = link[i].a;
    106 link[i].a = link[i].b;
    107 link[i].b = temp;
    108 }
    109 }
    110
    111 for(i=0;i<m;i++)
    112 for(j=i+1;j<m;j++)
    113 {
    114 if(isconnect(link[i],link[j]))
    115 {
    116 addEdge(i,j+m);
    117 addEdge(j+m,i);
    118 addEdge(i+m,j);
    119 addEdge(j,i+m);
    120 }
    121 }
    122
    123 two_SAT(2*m);
    124
    125 if(check(m))
    126 printf("panda is telling the truth...\n");
    127 else
    128 printf("the evil panda is lying again\n");
    129
    130 }
    131
    132 return0;
    133 }

      POJ 3678 Katu Puzzle
       http://poj.org/problem?id=3678
    大意:有n个点,每个点的权值Xi为0或1,满足以下m个条件:
    每个条件的格式如:
      Xa op Xb = c
     其中op为and,or,xor运算中的一种

    问是否存在满足上述条件的图?

    分析:
    构图,对于每个节点,可取0或1,分别对应于xa,xa+n
    那么:
    1.若Xa or Xb = 1
       a.若Xa=0必有Xb=1,故建边Xa->Xb+n
       b.若Xb=0必有Xa=1,建边 Xb->Xa+n
    2.若Xa or Xb = 0
       a.必有Xa,Xb均为0,即添边Xa->Xb,xb->xa
       b. Xa 或者Xb=0均非法,即添边xa+n->xa,xb+n->xb

    3.若Xa and Xb = 1
       a.必有xa,xb均为1,故建边xa+n->xb+n,xb+n->xa+n
       b.xa=0或xb=0非法,建边xa->xa+n,xb->xb+n

    4.若Xa and Xb =0
       a.若Xa = 1必有Xb = 0 即建边xa+n->xb
       b.若Xb = 1必有Xa = 0 即建边xb+n->xa

    5.若Xa xor Xb= 1
       a.xa+n -> xb
       b.xb -> xa+n
       c.xb+n -> xa
       d.xa ->xb+n  
    6.若Xa xor Xb = 0
       a.xa->xb
       b.xb->xa
       c.xa+n->xb+n
       d.xb+n->xa+n

     

    View Code
    1 #include<stdio.h>
    2 #include<string.h>
    3 constint N =1000+10;
    4 #include<vector>
    5 usingnamespace std;
    6 vector<int>edge[N*2];//正向边
    7 vector<int>iedge[N*2];//逆向边
    8
    9 inline void addEdge(int s,int t)
    10 {
    11 edge[s].push_back(t);
    12 iedge[t].push_back(s);
    13 }
    14
    15 bool visited[N*2];
    16 int color[N*2];//color[i]标记i点所属分量
    17 vector<int>stack;//记录拓扑排序时的栈
    18 void dfs1(int p)//dfs1实际是在求拓扑图,拓扑排序后的信息逆序存于statck中
    19 {
    20 if(visited[p]==true)return;
    21 visited[p]=true;
    22 int sz = edge[p].size();
    23 int i;
    24 for(i=0;i<sz;i++)
    25 {
    26 if(!visited[edge[p][i]])
    27 dfs1(edge[p][i]);
    28 }
    29
    30 stack.push_back(p);
    31 }
    32
    33 void dfs2(int n,int group)
    34 {
    35 if(visited[n]==true)return;
    36 visited[n]=true;
    37 int i,sz = iedge[n].size();
    38 for(i=0;i<sz;i++)
    39 {
    40 if(!visited[iedge[n][i]])
    41 dfs2(iedge[n][i],group);
    42 }
    43 color[n]=group;
    44 }
    45 void two_SAT(int n)//n为点的个数
    46 {
    47 memset(visited,false,sizeof(visited));
    48 int i;
    49 stack.clear();
    50 for(i=0;i<n;i++)
    51 {
    52 if(!visited[i])dfs1(i);
    53 }
    54
    55 memset(visited,false,sizeof(visited));
    56
    57 int group =0;
    58 int sz = stack.size();
    59 for(i=sz-1;i>=0;i--)
    60 {
    61 if(!visited[stack[i]])
    62 dfs2(stack[i],group++);
    63 }
    64
    65 // printf("group = %d \n",group);
    66
    67 }
    68
    69 //判断Ai,Ai'是否属于同一个强连通分量
    70 bool check(int m)
    71 {
    72 for(int i=0;i<m;i++)
    73 if(color[i]==color[i+m])returnfalse;
    74 returntrue;
    75 }
    76
    77 void processAnd(int a,int b,int c,int n)//处理processAnd
    78 {
    79 if(c==0)//a,b不能同时取1
    80 {
    81 addEdge(a+n,b);//a=1 =>b=0
    82 addEdge(b+n,a);//b=1 =>a=0
    83 }else
    84 {
    85 addEdge(a,a+n);//a = 0必不合法
    86 addEdge(b,b+n);//b = 0必不合法
    87 addEdge(a+n,b+n);
    88 addEdge(b+n,a+n);
    89 }
    90 }
    91
    92 void ProcessOr(int a,int b,int c,int n)
    93 {
    94 if(c==0)
    95 {
    96 addEdge(a+n,a);//a=1必不合法
    97 addEdge(b+n,b);//b=1必不合法
    98 addEdge(a,b);
    99 addEdge(b,a);
    100 }
    101 else
    102 {
    103 addEdge(a,b+n);//a=0 => b = 1
    104 addEdge(b,a+n);//b=0 => a = 1
    105 }
    106 }
    107
    108 inline void Processxor(int a,int b,int c,int n)
    109 {
    110 if(c==1)
    111 {
    112 addEdge(a,b+n);
    113 addEdge(b+n,a);
    114 addEdge(a+n,b);
    115 addEdge(b,a+n);
    116 }
    117 else
    118 {
    119 addEdge(a+n,b+n);
    120 addEdge(b+n,a+n);
    121 addEdge(a,b);
    122 addEdge(b,a);
    123 }
    124 }
    125 int main()
    126 {
    127 int n,m;
    128 int a,b,c;
    129 char op[10];
    130
    131 while(scanf("%d%d",&n,&m)!=EOF)
    132 {
    133 int i;
    134 for(i=0;i<2*n+1;i++)
    135 {
    136 edge[i].clear();
    137 iedge[i].clear();
    138 }
    139 while(m--)
    140 {
    141
    142 scanf("%d%d%d%s",&a,&b,&c,op);
    143 if(op[0]=='A')
    144 processAnd(a,b,c,n);
    145 else
    146 if(op[0]=='O')
    147 ProcessOr(a,b,c,n);
    148 else
    149 if(op[0]=='X')
    150 Processxor(a,b,c,n);
    151
    152 }
    153
    154 two_SAT(2*n);
    155
    156 if(check(n))
    157 printf("YES\n");
    158 else
    159 printf("NO\n");
    160
    161 }
    162
    163 return0;
    164 }
  • 相关阅读:
    BAT系列(一)— CNN
    图像处理基本知识总结(一)
    机器学习(二十一)— 特征工程、特征选择、归一化方法
    C++(三)— 二维容器
    代码题(19)— 组合与排列
    代码题(18)— 子集
    机器学习(二十)— 常见统计学习方法总结(一)
    【angularjs】使用angular搭建项目,获取dom元素
    【css】常用css
    【angularjs】使用angular搭建项目,图片懒加载资料
  • 原文地址:https://www.cnblogs.com/AndreMouche/p/1988740.html
Copyright © 2011-2022 走看看