zoukankan      html  css  js  c++  java
  • BZOJ 4945 UOJ #317 NOI2017 游戏 2-SAT 拓扑排序

    http://uoj.ac/problem/317

    https://www.lydsy.com/JudgeOnline/problem.php?id=4945

    我现在的程序uoj的额外数据通过不了,bzoj应该是原版数据所以可以过??

    x不超过8个所以2^8枚举一下就可以了。每个可以选择的状态实际上只有两个所以还是2-SAT。

    2-SAT的图需要满足对偶性,所以逆否连边很有用。

    我之前不会这种问题怎么输出方案,输出方案的方法就是tarjan之后topsort,再对每个强连通分量决定选还是不选(把矛盾的都不选,和矛盾相反的选,具体看代码里的dfs1函数)。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<cmath>
      5 #include<iostream>
      6 using namespace std;
      7 #define LL long long
      8 const int maxn=300010;
      9 int n,d,fla=0,m;
     10 char ch[maxn],ch1[2],ch2[2],ans[maxn];
     11 int pos[10]={};
     12 struct node{
     13     int id1,x,id2,y;
     14 }a[maxn];
     15 struct nod{
     16     int y,next;
     17 };nod e[maxn],e1[maxn];
     18 int head[maxn]={},head1[maxn]={},tot=0,tot1=0;
     19 int low[maxn]={},dfn[maxn]={},sta[maxn]={},bel[maxn]={},cnt=0,tai=0,tly=0;
     20 int de[maxn]={},op[maxn]={}; bool vis[maxn]={};
     21 int ob[maxn]={},dd[maxn]={},co[maxn]={};
     22 int q[maxn]={},s=0,t=0;
     23 inline void init(int x,int y){
     24     e[++tot].y=y;e[tot].next=head[x];head[x]=tot;
     25 }
     26 inline void init1(int x,int y){
     27     e1[++tot1].y=y;e1[tot1].next=head1[x];head1[x]=tot1;
     28 }
     29 void tarjan(int x){
     30     sta[++tai]=x;low[x]=dfn[x]=++cnt;vis[x]=1;
     31     for(int i=head[x];i;i=e[i].next){
     32         if(!dfn[e[i].y]){
     33             tarjan(e[i].y);
     34             low[x]=min(low[x],low[e[i].y]);
     35         }
     36         else if(vis[e[i].y]) low[x]=min(low[x],dfn[e[i].y]);
     37     }
     38     if(low[x]==dfn[x]){
     39         int w;tly++;
     40         do{
     41             w=sta[tai--];
     42             bel[w]=tly;vis[w]=0;
     43         }while(w!=x);
     44     }
     45 }
     46 void Check(){
     47     memset(dfn,0,sizeof(dfn));
     48     memset(head,0,sizeof(head));
     49     tot=0;cnt=0;tly=0;
     50     int aa,bb,cc;
     51     for(int i=1;i<=n;i++){
     52         aa=(ch[i]-'a')*n+i;bb=(aa+n-1)%(3*n)+1;cc=(bb+n-1)%(3*n)+1;
     53         de[aa]=1;de[bb]=0;de[cc]=0;
     54         op[bb]=cc;op[cc]=bb;
     55     }
     56     for(int i=1;i<=m;i++){
     57         aa=a[i].x*n+a[i].id1;bb=a[i].y*n+a[i].id2;
     58         if(aa==bb||de[aa])continue;
     59         if(a[i].id1==a[i].id2||de[bb]){
     60             init(aa,op[aa]);//aa一定到op[aa]即表明aa不能选
     61         }
     62         else{init(op[bb],op[aa]);init(aa,bb);}//图要对偶所以aa连bb逆否也连一下
     63     }
     64     for(int i=1;i<=3*n;i++){
     65         if(de[i]||dfn[i])continue;
     66         tarjan(i);
     67     }
     68     for(int i=1;i<=3*n;i++){
     69         if(de[i])continue;
     70         if(bel[i]==bel[op[i]])return;
     71         ob[bel[i]]=bel[op[i]];ob[bel[op[i]]]=bel[i];
     72     }
     73     fla=1;
     74 }
     75 void dfs(int x){
     76     if(x==d+1){
     77         Check();return;
     78     }
     79     ch[pos[x]]='a';dfs(x+1);
     80     if(fla)return;
     81     ch[pos[x]]='b';dfs(x+1);
     82 }
     83 void dfs1(int x){
     84     if(co[x]!=-1)return;
     85     co[x]=0;co[ob[x]]=1;
     86     for(int i=head1[x];i;i=e1[i].next)dfs1(e1[i].y);
     87 }
     88 int main(){
     89     scanf("%d%d%s%d",&n,&d,ch+1,&m);
     90     for(int i=1;i<=n;i++)if(ch[i]=='x')pos[++pos[0]]=i;
     91     for(int i=1;i<=m;i++){ 
     92         scanf("%d%s%d%s",&a[i].id1,ch1,&a[i].id2,ch2);
     93         a[i].x=ch1[0]-'A';a[i].y=ch2[0]-'A';
     94     }
     95     dfs(1);
     96     if(!fla){
     97         printf("-1
    ");return 0;
     98     }
     99     memset(co,-1,sizeof(co));
    100     for(int i=1;i<=3*n;i++){//强连通分量缩点后拓扑序
    101         if(de[i])continue;
    102         for(int j=head[i];j;j=e[j].next)
    103             if(bel[e[j].y]!=bel[i]){init1(bel[e[j].y],bel[i]);++dd[bel[i]];}
    104     }
    105     for(int i=1;i<=tly;i++)if(!dd[i])q[++t]=i;
    106     while(s<t){
    107         int x=q[++s];
    108         for(int i=head1[x];i;i=e1[i].next){
    109             --dd[e1[i].y];
    110             if(!dd[e1[i].y])q[++t]=e1[i].y;
    111         }
    112         if(co[x]!=-1)continue;
    113         dfs1(ob[x]);
    114     }
    115     for(int i=1;i<=3*n;i++){if((!de[i])&&co[bel[i]]==1)ans[(i-1)%n]='A'+(i-1)/n;}
    116     printf("%s",ans);
    117     return 0;
    118 }
    View Code

  • 相关阅读:
    leetcode------Sum Root to Leaf Numbers
    TesserOCR训练
    【转载】C#.Net 创建网页快捷方式
    错误:没有为扩展名“.html”注册的生成提供程序。
    【转载】错误 CS0016: 未能写入输出文件“c:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files/.........dll”--“拒绝访问。 ”
    [转载]ASP.NET对路径"xxxxx"的访问被拒绝的解决方法小结
    [转载]ASP.NET对路径"xxxxx"的访问被拒绝的解决方法小结
    [转载]AFX_MANAGE_STATE关于资源切换
    OD鲜为人知的小技巧--搜索通配符(关键字)
    【转载】汇编跳转指令集
  • 原文地址:https://www.cnblogs.com/137shoebills/p/9099197.html
Copyright © 2011-2022 走看看