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 }
View Code

相关文章:

  • 2021-06-22
  • 2022-01-22
  • 2021-05-16
  • 2022-01-25
  • 2021-12-02
  • 2021-12-16
  • 2021-08-21
  • 2022-02-12
猜你喜欢
  • 2021-08-27
  • 2021-07-04
  • 2021-12-11
  • 2021-09-10
  • 2022-12-23
  • 2021-09-15
  • 2021-11-17
相关资源
相似解决方案