Gym - 100502A Amanda Lounges (2-SAT)

之前的解法

其实二分图染色问题可以看成2-SAT问题的一个特例,只需要稍微修改一下板子,在对每个连通块dfs的时候每个点黑白都试一下,取个最小值即可,因为二分图染色比较特殊,各个连通块相互独立,因此不存在回溯的问题(一般情况下2-SAT问题对每个点的黑白染色都分别判断的话需要回溯)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef double db;
 5 const int N=2e5+10,inf=0x3f3f3f3f;
 6 struct TWO_SAT {
 7     int n,hd[N],ne,col[N],sta[N],tp;
 8     struct E {int v,f,g,nxt;} e[N*4];
 9     void link(int u,int v,int f,int g) {
10         e[ne]= {v,f,g,hd[u]},hd[u]=ne++;
11         e[ne]= {u,!g,!f,hd[v]},hd[v]=ne++;
12     }
13     void init(int _n) {
14         n=_n,ne=tp=0;
15         for(int i=1; i<=n; ++i)hd[i]=-1;
16     }
17     bool dfs(int u,int c) {
18         if(~col[u])return col[u]==c;
19         col[u]=c,sta[tp++]=u;
20         for(int i=hd[u]; ~i; i=e[i].nxt) {
21             int v=e[i].v,f=e[i].f,g=e[i].g;
22             if(f==col[u]&&!dfs(v,g))return 0;
23         }
24         return 1;
25     }
26     int check() {
27         int ret=0;
28         for(int i=1; i<=n; ++i)col[i]=-1;
29         for(int i=1; i<=n; ++i)if(!~col[i]) {
30                 tp=0;
31                 int mi=inf;
32                 if(dfs(i,0)) {
33                     int cnt=0;
34                     for(int i=0; i<tp; ++i)if(col[sta[i]]==1)++cnt;
35                     mi=min(mi,cnt);
36                 }
37                 for(; tp; col[sta[--tp]]=-1);
38                 if(dfs(i,1)) {
39                     int cnt=0;
40                     for(int i=0; i<tp; ++i)if(col[sta[i]]==1)++cnt;
41                     mi=min(mi,cnt);
42                 } else {
43                     for(; tp; col[sta[--tp]]=-1);
44                     dfs(i,0);
45                 }
46                 if(mi==inf)return -1;
47                 ret+=mi;
48             }
49         return ret;
50     }
51 } twosat;
52 int n,m;
53 
54 int main() {
55     scanf("%d%d",&n,&m);
56     twosat.init(n);
57     while(m--) {
58         int u,v,c;
59         scanf("%d%d%d",&u,&v,&c);
60         if(c==0)twosat.link(u,u,1,0),twosat.link(v,v,1,0);
61         else if(c==1)twosat.link(u,v,1,0),twosat.link(u,v,0,1);
62         else if(c==2)twosat.link(u,u,0,1),twosat.link(v,v,0,1);
63     }
64     int ans=twosat.check();
65     if(ans==-1)puts("impossible");
66     else printf("%d\n",ans);
67     return 0;
68 }

 

posted @ 2021-04-02 16:41  jrltx  阅读(48)  评论(0编辑  收藏  举报