ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

洛谷P3825/LOJ2305/UOJ317/BZOJ4945[NOI2017]游戏(2-SAT)

2019-08-15 16:00:10  阅读:205  来源: 互联网

标签:GCC UOJ317 洛谷 int lowv NOI2017 pragma include optimize


没有x地图的话是一个比较明显的2-SAT。对于$(i,h_i,j,h_j)$,若$h_i$不能用,则无视掉;若$h_j$不能用,则连边$(i,i')$,表示选$i$就要选$i'$,那么按照2-SAT的定义,$i$肯定不会出现在答案中;否则连边$(i,j),(j',i')$(若$j$不选$h_j$,则$i$必定不选$h_i$)。

而对于x地图,最简单的想法是$O(3^d)$枚举,肯定TLE,但是我们发现若禁掉A,可选B、C;禁掉B,可选A、C。这样已经把A、B、C都考虑了一遍,也就是说枚举只用$O(2^d)$,总共$O(2^d(n+m))$,可过。

#include<cstdio>
#include<cctype>
#include<cstring>
const int N=50005;
const int M=100050;
char rB[1<<21],*rS,*rT;
inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,1<<21,stdin),rS==rT)?EOF:*rS++;}
inline char rdc(){
    char c=gc();
    while(!isalpha(c))c=gc();
    return c;
}
inline int rdi(){
    char c=gc();
    while(!isdigit(c))c=gc();
    int x=c&15;
    for(c=gc();isdigit(c);c=gc())x=(x<<3)+(x<<1)+(c&15);
    return x;
}
int a[M],b[M],G[N<<1],to[M<<1],nxt[M<<1],sz=0,dfn[N<<1],col[N<<1],dfsc,st[N<<1],sl=-1,cnt,idx[10],idc=0,n;
char ban[N],x[M],y[M],ans[N];
inline void adde(int u,int v){
    to[++sz]=v;nxt[sz]=G[u];G[u]=sz;
}
inline int getid(int x,char c){
    if(ban[x]!='C')return x+n*(c=='C');
    return x+n*(c=='B');
}
inline int gotid(int x){  //已知x求x'
    return x>n?x-n:x+n;
}
int dfs(int u){
    int i,v,lowu=dfn[u]=++dfsc,lowv;
    st[++sl]=u;
    for(i=G[u];i;i=nxt[i])if(!dfn[v=to[i]]){
        lowv=dfs(v);
        if(lowv<lowu)lowu=lowv;
    }else if(!col[v=to[i]]&&dfn[v]<lowu)lowu=dfn[v];
    if(lowu==dfn[u]){
        ++cnt;
        do{
            v=st[sl--];
            col[v]=cnt;
        }while(v!=u);
    }
    return lowu;
}
inline bool check(){
    int i;
    memset(dfn,0,sizeof(dfn));
    memset(col,0,sizeof(col));dfsc=cnt=0;
    for(i=1;i<=(n<<1);++i)if(!dfn[i])dfs(i);
    for(i=1;i<=n;++i){
        if(col[i]==col[i+n])return 0;
        if(col[i]<col[i+n])ans[i]=ban[i]=='A'?'B':'A';
        else ans[i]=ban[i]=='C'?'B':'C';
    }
    for(i=1;i<=n;++i)putchar(ans[i]);
    return 1;
}
int main(){
    int m,i,u,v,S;
    char c;
    n=rdi();rdi();
    for(i=1;i<=n;++i)if((c=toupper(rdc()))=='X')idx[idc++]=i;
    else ban[i]=c;
    m=rdi();
    for(i=0;i<m;++i){a[i]=rdi();x[i]=rdc();b[i]=rdi();y[i]=rdc();}
    for(S=0;S<(1<<idc);++S){
        memset(G,0,sizeof(G));sz=0;
        for(i=0;i<idc;++i)ban[idx[i]]=(S&(1<<i))?'A':'B';
        for(i=0;i<m;++i)if(ban[a[i]]!=x[i]){
            if(ban[b[i]]==y[i]){
                u=getid(a[i],x[i]);
                adde(u,gotid(u));
            }else{
                u=getid(a[i],x[i]);v=getid(b[i],y[i]);
                adde(u,v);adde(gotid(v),gotid(u));
            }
        }
        if(check())return 0;
    }
    putchar('-');putchar('1');
    return 0;
}
View Code

但是在UOJ上又神仙出了毒瘤数据,把$O(2^d(n+m))$卡满了,导致卡常也过不去,这时就需要随机化乱搞了,把$0$到$2^d-1$扔进数组里,random_shuffle一下(事实证明手写的没STL的好),然后在时限里面尽可能的多跑几组数据,时限快到了就输出-1(我卡到1.983s,1.98sWA,1.985sTLE)

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
//玄学优化
#include<cstdio>
#include<cctype>
#include<cstring>
#include<ctime>
#include<algorithm>
using namespace std;
const int N=50005;
const int M=100050;
char rB[1<<21],*rS,*rT;
inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,1<<21,stdin),rS==rT)?EOF:*rS++;}
inline char rdc(){
    char c=gc();
    while(!isalpha(c))c=gc();
    return c;
}
inline int rdi(){
    char c=gc();
    while(!isdigit(c))c=gc();
    int x=c&15;
    for(c=gc();isdigit(c);c=gc())x=(x<<3)+(x<<1)+(c&15);
    return x;
}
int a[M],b[M],G[N<<1],to[M<<1],nxt[M<<1],sz=0,dfn[N<<1],col[N<<1],dfsc,st[N<<1],sl=-1,cnt,idx[10],idc=0,n,S[270];
char ban[N],x[M],y[M],ans[N];
inline void Swap(int &a,int &b){int t=a;a=b;b=t;}
inline void adde(int u,int v){
    to[++sz]=v;nxt[sz]=G[u];G[u]=sz;
}
inline int getid(int x,char c){
    if(ban[x]!='C')return x+n*(c=='C');
    return x+n*(c=='B');
}
inline int gotid(int x){
    return x>n?x-n:x+n;
}
int dfs(int u){
    int i,v,lowu=dfn[u]=++dfsc,lowv;
    st[++sl]=u;
    for(i=G[u];i;i=nxt[i])if(!dfn[v=to[i]]){
        lowv=dfs(v);
        if(lowv<lowu)lowu=lowv;
    }else if(!col[v=to[i]]&&dfn[v]<lowu)lowu=dfn[v];
    if(lowu==dfn[u]){
        ++cnt;
        do{
            v=st[sl--];
            col[v]=cnt;
        }while(v!=u);
    }
    return lowu;
}
inline bool check(){
    int i;
    memset(dfn,0,sizeof(dfn));
    memset(col,0,sizeof(col));dfsc=cnt=0;
    for(i=1;i<=(n<<1);++i)if(!dfn[i])dfs(i);
    for(i=1;i<=n;++i){
        if(col[i]==col[i+n])return 0;
        if(col[i]<col[i+n])ans[i]=ban[i]=='A'?'B':'A';
        else ans[i]=ban[i]=='C'?'B':'C';
    }
    for(i=1;i<=n;++i)putchar(ans[i]);
    return 1;
}
int main(){
    int m,i,k,u,v;
    char c;
    n=rdi();rdi();
    for(i=1;i<=n;++i)if((c=toupper(rdc()))=='X')idx[idc++]=i;
    else ban[i]=c;
    m=rdi();
    for(i=0;i<m;++i){a[i]=rdi();x[i]=rdc();b[i]=rdi();y[i]=rdc();}
    for(i=0;i<(1<<idc);++i)S[i]=i;
    srand(time(NULL));
    random_shuffle(S,S+(1<<idc));
    for(k=0;k<(1<<idc)&&clock()<1.983*CLOCKS_PER_SEC;++k){
        memset(G,0,sizeof(G));sz=0;
        for(i=0;i<idc;++i)ban[idx[i]]=(S[k]&(1<<i))?'A':'B';
        for(i=0;i<m;++i)if(ban[a[i]]!=x[i]){
            if(ban[b[i]]==y[i]){
                u=getid(a[i],x[i]);
                adde(u,gotid(u));
            }else{
                u=getid(a[i],x[i]);v=getid(b[i],y[i]);
                adde(u,v);adde(gotid(v),gotid(u));
            }
        }
        if(check())return 0;
    }
    putchar('-');putchar('1');
    return 0;
}
View Code

最后提供一个判断解可行性的spj(-1要手工检查一下):

#include<cstdio>
#include<cctype>
#include<cstring>
char s[50005],ans[50005];
int main(){
    FILE *fin=fopen("game.in","rb"),*ftest=fopen("game.out","rb");
    int n,m,i,u,v;
    char x,y;
    fscanf(fin,"%d%d%s",&n,&m,s+1);
    for(i=1;i<=n;++i)s[i]=toupper(s[i]);
    fscanf(ftest,"%s",ans+1);
    if(strlen(ans+1)!=n){
        puts("Too long or too short.");
        return 0;
    }
    for(i=1;i<=n;++i)if(s[i]==ans[i]){
        printf("Running the car %d which is banned.\n",i);
        return 0;
    }
    fscanf(fin,"%d",&m);
    for(i=1;i<=m;++i){
        fscanf(fin,"%d %c %d %c",&u,&x,&v,&y);
        if(ans[u]==x&&ans[v]!=y){
            printf("Do not follow rule %d.\n",i);
            return 0;
        }
    }
    puts("Accepted.");
    return 0;
}
View Code

 

标签:GCC,UOJ317,洛谷,int,lowv,NOI2017,pragma,include,optimize
来源: https://www.cnblogs.com/sunshine-chen/p/11358508.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有