zoukankan      html  css  js  c++  java
  • 图论:2-SAT

    先象征性地描述一下问题:一组(或者一个)东西有且仅有两种选择,要么选这个,要么选那个,还有一堆的约束条件

    图论问题,当然是建边跑图喽

    给出模型:

    模型一:两者(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’就只能选择B’,选择了B’就只能选择A’
      连边A→B,B→A,A’→B’,B’→A’
    
    模型四:两者(A,A’)必取A
    
      那么,那么,该怎么说呢?先说连边吧。
      连边A’→A

    题目POJ3683

    然后说一下这个题的意思:

    如果某两个婚礼进行仪式的时间有重合

    那么就存在了矛盾关系,通过这些关系连边

    Tarjan缩点重新建图(这里建反向图),判断

    将一个未着色点 x 上色同时,把与它矛盾的点 y 以及 y 的所有子孙节点上另外一种颜色

    上色完成后,进行拓扑排序,选择一种颜色的点输出就是一组可行解

    介绍一下实现:

    int n,cnt,scc,ind,top;
    int a[maxn],b[maxn],belong[maxn],op[maxn];
    bool inq[maxn];int dfn[maxn],low[maxn],q[maxn],col[maxn];
    int g[maxn],gd[maxn],d[maxn];
    struct Edge{int t,next;}e[maxm],ed[maxm];

    ind是自增的用来记录dfn,scc是连通分量个数

    belong用于存每一个点属于哪一个连通分量

    然后op用来记录同一组的互斥条件

    col用来存颜色

    d用来存点的度数,便于拓扑排序

    下面给出完整实现,感觉这个题可以很好地拆成几个很好地模板(就比如说拓扑排序,重新建图,强连通缩点,哈哈)

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 const int maxn=2005;
      6 const int maxm=2000005;
      7 int n,cnt,scc,ind,top;
      8 int a[maxn],b[maxn],belong[maxn],op[maxn];
      9 bool inq[maxn];int dfn[maxn],low[maxn],q[maxn],col[maxn];
     10 int g[maxn],gd[maxn],d[maxn];
     11 struct Edge{int t,next;}e[maxm],ed[maxm];
     12 void addedge(int u,int v)
     13 {
     14     e[++cnt].t=v;e[cnt].next=g[u];
     15     g[u]=cnt;
     16 }
     17 void addedge2(int u,int v)
     18 {
     19     d[v]++;
     20     ed[++cnt].t=v;ed[cnt].next=gd[u];
     21     gd[u]=cnt;
     22 }
     23 inline int read()
     24 {
     25     int x=0,f=1;char ch=getchar();
     26     while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
     27     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     28     return x*f;
     29 }
     30         //a[2i]-b[2i]前半程
     31         //a[2i-1]-b[2i-1]后半程 
     32 bool jud(int x,int y)
     33 {
     34     if(b[x]<=a[y]||a[x]>=b[y]) return 0;
     35     return 1;
     36 }
     37 void build()
     38 {
     39     for(int i=1;i<=n;i++)
     40         for(int j=i+1;j<=n;j++)
     41         {
     42             if(jud(2*i,2*j))
     43             {
     44                 addedge(2*i,2*j-1);
     45                 addedge(2*j,2*i-1);
     46             }
     47             if(jud(2*i,2*j-1))
     48             {
     49                 addedge(2*i,2*j);
     50                 addedge(2*j-1,2*i-1);
     51             }
     52             if(jud(2*i-1,2*j))
     53             {
     54                 addedge(2*i-1,2*j-1);
     55                 addedge(2*j,2*i);
     56             }
     57             if(jud(2*i-1,2*j-1))
     58             {
     59                 addedge(2*i-1,2*j);
     60                 addedge(2*j-1,2*i);
     61             }
     62         }
     63 }
     64 void tarjan(int x)
     65 {
     66     //cout<<x<<endl;
     67     dfn[x]=low[x]=++ind;
     68     q[++top]=x;inq[x]=1;
     69     for(int tmp=g[x];tmp;tmp=e[tmp].next)
     70         if(!dfn[e[tmp].t])
     71         {
     72             tarjan(e[tmp].t);
     73             low[x]=min(low[e[tmp].t],low[x]);
     74         }
     75         else if(inq[e[tmp].t])
     76             low[x]=min(dfn[e[tmp].t],low[x]);
     77         if(low[x]==dfn[x])
     78         {
     79             int temp=0;scc++;
     80             while(temp!=x)
     81             {
     82                 temp=q[top--];
     83                 inq[temp]=0;
     84                 belong[temp]=scc;
     85             }
     86         }
     87 }
     88 void rebuild()
     89 {
     90     cnt=0;
     91     for(int x=1;x<=2*n;x++)
     92         for(int tmp=g[x];tmp;tmp=e[tmp].next)
     93             if(belong[x]!=belong[e[tmp].t])
     94             {
     95                 //cout<<belong[e[tmp].t]<<" "<<belong[x]<<endl;
     96                 addedge2(belong[e[tmp].t],belong[x]);
     97             }
     98 
     99 }
    100 void dfs(int x)
    101 {
    102     if(col[x]) return;
    103     col[x]=-1;
    104     for(int tmp=gd[x];tmp;tmp=ed[tmp].next)
    105         dfs(ed[tmp].t);
    106 }
    107 void topsort()
    108 {
    109     for(int i=1;i<=scc;i++)
    110         if(!d[i]) q[++top]=i;
    111     while(top)
    112     {
    113         int temp=q[top--];
    114         //cout<<temp<<endl;
    115         if(col[temp]) continue;
    116         col[temp]=1;dfs(op[temp]);
    117         for(int tmp=gd[temp];tmp;tmp=ed[tmp].next)
    118         {
    119             d[ed[tmp].t]--;
    120             if(!d[ed[tmp].t]) q[++top]=ed[tmp].t;
    121         }
    122     }
    123 }
    124 void print(int x)
    125 {
    126     printf("%.2d:",x/60);
    127     printf("%.2d ",x%60);
    128 }
    129 int main()
    130 {
    131     n=read();
    132     int x;
    133     for(int i=1;i<=n;i++)
    134     {
    135         //a[2i]-b[2i]前半程
    136         //a[2i-1]-b[2i-1]后半程 
    137         a[2*i]=read();
    138         a[2*i]=a[2*i]*60+read();
    139         b[2*i-1]=read();
    140         b[2*i-1]=b[2*i-1]*60+read();
    141         x=read();
    142         b[2*i]=a[2*i]+x;
    143         a[2*i-1]=b[2*i-1]-x;
    144     }
    145     build();
    146     for(int i=1;i<=2*n;i++)
    147         if(!dfn[i]) tarjan(i);
    148     for(int i=1;i<=n;i++)
    149         if(belong[2*i]==belong[2*i-1])
    150             {puts("NO");return 0;}
    151     puts("YES");
    152     rebuild();
    153     for(int i=1;i<=n;i++)
    154     {
    155         op[belong[2*i]]=belong[2*i-1];
    156         op[belong[2*i-1]]=belong[2*i];
    157     }
    158     topsort();
    159     for(int i=1;i<=n;i++)
    160         if(col[belong[2*i]]==1)
    161             print(a[2*i]),print(b[2*i]),puts("");
    162         else print(a[2*i-1]),print(b[2*i-1]),puts("");
    163     return 0;
    164 }
  • 相关阅读:
    toString和equals两个比较常见的重写方式
    Java内构造函数、关键字、权限修饰符、访问控制及面向对象的特性!
    java中一个重要思想:面向对象
    JAVA基础汇总及例题详解
    java数据类型转换和数组总结
    java的数据基础
    HTML中的表格、表单元素与框架的构建
    linux命令学习(持续更新......)
    javascript bind在回调中精简匿名函数的用法
    CSS 文字超长省略显示并隐藏超长部分
  • 原文地址:https://www.cnblogs.com/aininot260/p/9457908.html
Copyright © 2011-2022 走看看