• 2-sat


    2-SAT算法本身并不难,关键是连边,不过只需要充分理解好边的概念:a->b即选a必选b。

    a、b不能同时选:选了a就要选b',选了b就要选a'。

    a、b必须同时选:选了a就要选b,选了b就要选a,选了a'就要选b',选了b'就要选a'。

    a、b必须选一个:选了a就要选b',选了b就要选a',选了a'就要选b,选了b'就要选a。

    a、b至少选一个:选了a' 就要选b,选了b' 就要选a

    ※a必须选:a'->a。

    https://ac.nowcoder.com/acm/contest/327/F
    题目描述:处女座进行了一次探险,发现了一批宝藏。如果他获得这批宝藏,那么他一辈子都不需要工作了。但是处女座遇到了一个难题。

    宝藏被装在n个宝箱里,宝箱编号为1,2,…,n,只有所有宝箱在某一时间被打开,处女座才能获得宝藏。有m个开关,每个开关控制k个宝箱,如果按下一个开关,那么这k个宝箱的开关状态都会发生改变(从开启变成关闭,从关闭变成开启),处女座想知道他能否获得这批宝藏

    题解:2-sat

      1 #include<iostream>
      2 #include<string>
      3 #include<algorithm>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<cstring>
      7 using namespace std;
      8 typedef long long ll;
      9 const int maxn=4e5+5;
     10 vector<int>g[maxn];
     11 int a[maxn],dfn[maxn<<1],low[maxn<<1],col[maxn<<1],head[maxn<<1],stk[maxn<<1],tim,tnt,cnt,col0;
     12 bool instk[maxn<<1];
     13 struct edge{
     14     int y;
     15     int x;
     16     int nex;
     17 }e[maxn<<1];
     18 void adde(int q,int w){
     19     e[cnt].x=q;
     20     e[cnt].y=w;
     21     e[cnt].nex=head[q];
     22     head[q]=cnt++;
     23 }
     24 void tarjan(int u){
     25     dfn[u]=low[u]=++tim;
     26     instk[u]=1;
     27     stk[++tnt]=u;
     28     for(int i=head[u];i!=-1;i=e[i].nex){
     29         int v=e[i].y;
     30         if(!dfn[v]){
     31             tarjan(v);
     32             low[u]=min(low[u],low[v]);
     33         }
     34         else if(instk[v]){
     35             low[u]=min(low[u],dfn[v]);
     36         }
     37     }
     38     if(dfn[u]==low[u]){
     39         col0++;
     40         int x;
     41         do{
     42             x=stk[tnt];
     43             col[x]=col0;
     44             instk[x]=0;
     45             tnt--;
     46         }while(x!=u);
     47     }
     48 }
     49 int main(){
     50     int n,m;
     51     scanf("%d%d",&n,&m);
     52     memset(head,-1,sizeof(head));
     53     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
     54     for(int i=1;i<=m;i++){
     55         int k;
     56         scanf("%d",&k);
     57         for(int j=0;j<k;j++){
     58             int x;
     59             scanf("%d",&x);
     60             g[x].push_back(i);
     61         }
     62     }
     63     int f=0;
     64     for(int i=1;i<=n;i++){
     65        if(g[i].size()==0){
     66             if(a[i]==1)
     67              {f=1;break;}
     68        }
     69        if(g[i].size()==1){
     70             if(a[i]){
     71                 adde(g[i][0]+m,g[i][0]);
     72             }
     73             else{
     74                 adde(g[i][0],g[i][0]+m);
     75             }
     76        }
     77        if(g[i].size()==2){
     78             if(a[i]){
     79                 adde(g[i][0],g[i][1]+m);
     80                 adde(g[i][1],g[i][0]+m);               
     81                 adde(g[i][1]+m,g[i][0]);
     82                 adde(g[i][0]+m,g[i][1]);
     83             }
     84             else{
     85                 adde(g[i][0],g[i][1]);
     86                adde(g[i][1],g[i][0]);               
     87                 adde(g[i][1]+m,g[i][0]+m);
     88                 adde(g[i][0]+m,g[i][1]+m);              
     89             }
     90        }
     91     }
     92     for(int i=1;i<=m*2;i++){
     93         if(!dfn[i]){
     94             tarjan(i);
     95         }
     96     }
     97     for(int i=1;i<=m;i++){
     98         if(col[i]==col[i+m]){
     99             f=1;
    100             break;
    101         }
    102     }
    103     if(!f)printf("YES
    ");
    104     else printf("NO
    ");
    105     return 0;
    106 }
    View Code
  • 相关阅读:
    iOS开发之单例模式
    XCode 安装 Alcatraz包管理器失败的处理
    iOS "此证书由未知颁发机构签名"此问题的解决方法
    Android WebView 使用
    BaseActivity
    定时周期执行指定的任务 ScheduledExecutorService
    SQLite数据库浅谈
    android 图片缓存
    Android之drawable state各个属性详解
    Android应用中如何启动另一个应用
  • 原文地址:https://www.cnblogs.com/MekakuCityActor/p/10556378.html
Copyright © 2020-2023  润新知