zoukankan      html  css  js  c++  java
  • codeforces568C. New Language

    传送门:http://codeforces.com/problemset/problem/568/C

    思路:贪心+2-sat判定

    先判定原串是否合法,合法就输出原串。

    否则贪心地从大到小枚举lcp,用2-sat判定

    求出最长的lcp后,对于后面每一位,分别贪心尝试最小的元辅音,先试字典序小的,用2-sat判定即可

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    const int maxn=405,maxm=maxn*maxn*5;
    using namespace std;
    int n,b[maxm][4],a[maxn],next[maxn][2],ans[maxn],m;
    char s[maxn];bool ch[maxn],allc,allv;//V:1 C:0
    int P(int x,int op){return op*n+x;}//V 2*(n-1)+1 C 2*(n-1) sb错误毁一生....n要-1,不然会有2*n+1的点 
    
    struct twosat{
    	int frm[maxm],pre[maxm],now[maxn],son[maxm],tot,tim,dfn[maxn],low[maxn],bel[maxn],bcnt,last,top,q[maxn];
    	bool ins[maxn];
    	void clear(){memset(now,0,sizeof(now)),tot=0;}
    	void add(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b,frm[tot]=a;}
    	void add(int a,int b,int c,int d){add(P(a,b),P(c,d));}
    	void del(){now[frm[tot]]=pre[tot],tot--;}
    	void tarjan(int x){
    		dfn[x]=low[x]=++tim,q[++top]=x,ins[x]=1;
    		for (int y=now[x];y;y=pre[y]){
    			if (!dfn[son[y]]) tarjan(son[y]),low[x]=min(low[x],low[son[y]]);
    			else if (ins[son[y]]) low[x]=min(low[x],dfn[son[y]]);
    		}
    		if (dfn[x]==low[x]){
    			bcnt++;int xx;
    			do{
    				xx=q[top--],bel[xx]=bcnt,ins[xx]=0;
    			}while (x!=xx);
    		}
    	}
    	bool check(){
            memset(ins,0,sizeof(ins));
            memset(dfn,0,sizeof(dfn)),tim=bcnt=top=0;
            for(int i=1;i<=(n<<1);++i) if(!dfn[i]) tarjan(i);
            for(int i=1;i<=n;++i) if(bel[P(i,0)]==bel[P(i,1)]) return 0;
            return 1;
        }
    }T;
    
    bool init(){
    	scanf("%s",s);memset(next,-1,sizeof(next));
    	for (int i=strlen(s)-1;i>=0;i--){
    		ch[i]=(s[i]=='V'),allc&=(s[i]=='C'),allv&=(s[i]=='V');
    		next[i][ch[i]]=i,next[i][ch[i]^1]=next[i+1][ch[i]^1];
    	}
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=m;i++){
    		int x,y;char s1[2],s2[2];
    		scanf("%d%s%d%s",&x,s1,&y,s2);
    		b[i][0]=x,b[i][1]=(s1[0]=='V');
    		b[i][2]=y,b[i][3]=(s2[0]=='V');
    	}
    	scanf("%s",s+1);
    	for (int i=1;i<=n;i++) a[i]=s[i]-'a';
    	bool can=1;
    	for (int i=1;i<=m;i++)
    		if (ch[a[b[i][0]]]==b[i][1]&&ch[a[b[i][2]]]!=b[i][3]){can=0;break;}
    	if (can) printf("%s
    ",s+1);
    	return can;
    }
    
    void work(){
    	int k=n,typek=-1;
    	T.clear();
    	for (int i=1;i<=m;i++){
    		T.add(P(b[i][0],b[i][1]),P(b[i][2],b[i][3]));
    		T.add(P(b[i][2],b[i][3]^1),P(b[i][0],!b[i][1]));
    	}
        for(int i=1;i<=n;++i){
            if(next[0][0]==-1) T.add(P(i,0),P(i,1));//只有一种可选,那每位都只有一种选法 
            if(next[0][1]==-1) T.add(P(i,1),P(i,0));
        }
        
    	for (k=n;k;k--){//第一个与原串不同的位置 ,从大到小贪心枚举lcp 
    		for (int i=1;i<k;i++) T.add(P(i,!s[i]=='V'),P(i,s[i]=='V'));
    		int t[5],cnt=0,nowc=a[k];
    		for (int pp=0;pp<=1;pp++)//枚举两种种类
    			if (next[nowc+1][pp]!=-1) t[++cnt]=next[nowc+1][pp];
    		sort(t+1,t+1+cnt);//优先选字典序小的 
    		for (int i=1;i<=cnt;i++){
    			for (int j=1;j<k;j++)
    				T.add(P(j,!ch[a[j]]),P(j,ch[a[j]]));
    			T.add(P(k,!ch[t[i]]),P(k,ch[t[i]]));
    			bool can=T.check();
    			for (int j=1;j<=k;j++)T.del();
    			if (can){typek=ch[t[i]];break;}
    		}
    		if (typek!=-1) break;
    	}
    	
    	if (!k){puts("-1");return;}
    	for (int i=1;i<k;i++) ans[i]=a[i];
    	
    	ans[k]=next[a[k]+1][typek];//确定第k位 
    	for (++k;k<=n;k++){
    		int t=0;
    		if (next[0][0]==-1||(next[0][1]!=-1&&next[0][0]>next[0][1])) t=1;//因为第k位已保证新串大于原串,所以后面只要枚举最小元辅音,优先选小的。
    		for (int i=1;i<k;i++) T.add(P(i,!ch[ans[i]]),P(i,ch[ans[i]]));
    		T.add(P(k,!t),P(k,t));
    		if (T.check()) ans[k]=next[0][t];else ans[k]=next[0][t^1];
    		for (int i=1;i<=k;i++) T.del();
    	}
    	for (int i=1;i<=n;i++) putchar(ans[i]+'a');puts("");
    }
    
    int main(){if (!init()) work();return 0;}
    /*
    VCV
    10 10
    1 V 7 V
    7 V 1 V
    10 V 8 C
    9 V 1 V
    6 C 2 C
    1 V 9 V
    2 C 5 C
    2 V 9 C
    2 C 10 C
    1 V 4 C
    bbbbcaabab
    
    ans:bbbcbababb
    */



  • 相关阅读:
    洛谷 P2958 [USACO09OCT]木瓜的丛林Papaya Jungle
    洛谷 P1400 塔
    10-2 集合之List
    主从数据库
    【单元测试】
    Pen Editor
    appendGrid
    动画
    JavaScript框架设计 第14章 动画引擎
    >>>
  • 原文地址:https://www.cnblogs.com/thythy/p/5493517.html
Copyright © 2011-2022 走看看