标签:
大致题意:
a~z每个字符分辅音和元音C和V,给出构词的法则,(pos1,kind1,pos2,kind2)如果位置1是kind1类型的字符,那么位置2必须是kind2类型的字符,求字典序不小于某个给定字符的合法构词(长度和给定的字符相等)若不存在输出-1
长度n<200,构词法则最多4*n*(n-1)条
思路:
可以贪心枚举每一位,假设前pos位答案和给定字符相等,那么pos+1位的字符必须比给定的字符pos+1位的字符大,然后pos+1位以后填充满足类型的最小字符
这样可以用2-sat dfs来输出解,2-sat dfs判解就有这个好处,可以按某种贪心(比如字典序)选解,然后构造出可行解
所以复杂度是 O(枚举*dfs) = O(n*m) = 1e6
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstring> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <string> #include <vector> #include <cstdio> #include <ctime> #include <bitset> #include <algorithm> #define SZ(x) ((int)(x).size()) #define ALL(v) (v).begin(), (v).end() #define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i) #define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i) #define REP(i,n) for ( int i=1; i<=int(n); i++ ) #define rep(i,n) for ( int i=0; i< int(n); i++ ) using namespace std; typedef long long ll; #define X first #define Y second typedef pair<int,int> pii; template <class T> inline bool RD(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void PT(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) PT(x / 10); putchar(x % 10 + '0'); } const int N = 433; bool val[26]; int n,m; vector<int>G[N]; void add_edge(int u,char ch1,int v,char ch2){ u = (u-1)*2+(ch1 == 'C'); v = (v-1)*2+(ch2 == 'C'); G[u].push_back(v); G[v^1].push_back(u^1); } int all; char s[N]; int lim; bool mark[N]; int sta[N],top; char ch0,ch1,ch2,ch3; char tmp[N]; bool dfs(int u) { if(mark[u^1]) return false; if(mark[u]) return true; if( u < 2*lim ){ int id = u/2; if ( val[s[id]-'a'] != (u&1) ) return false; } else if( u/2 == lim ){ if( (u&1) && ch1 == -1) return false; if( (u&1) == 0 && ch0 == -1) return false; }else if( u/2 > lim ){ if( (u&1) && ch3 == -1) return false; if( (u&1) == 0 && ch2 == -1) return false; } mark[u] = 1; sta[++top] = u; int sz=G[u].size(); for(int i = 0; i < sz;i++) { int v=G[u][i]; if( dfs(v) == false) return false; } return true; } bool judge() { memset(mark,0,sizeof(mark)); for(int i = 0;i < 2*n;i++) { if(!mark[i]&&!mark[i^1]) { top = 0; if( i < 2*lim ){ int id = i/2; if( val[s[id]-'a'] != (i&1) ) continue; if( dfs(i) == false ) return false; }else{ int u = i/2; if( u == lim){ if( val[s[lim]-'a'+1] != (i&1) ) continue; else{ if(dfs(i) == false) { for(int j = 1;j <= top; j++) mark[sta[j]] = 0; top = 0; if(dfs(i^1) == false) return false; } } }else{ if( val[0] != (i&1) ) continue; else{ if(dfs(i) == false) { for(int j = 1;j <= top; j++) mark[sta[j]] = 0; top = 0; if(dfs(i^1) == false) return false; } } } } } } return true; } int main(){ scanf("%s",tmp); cin>>n>>m; for(int i = 0; tmp[i]; i++){ if( tmp[i] == 'V') val[i] = 0; else val[i] = 1; } all = strlen(tmp); REP(i,m){ char ch1,ch2; int u,v; scanf("%d %c %d %c",&u,&ch1,&v,&ch2); add_edge(u,ch1,v,ch2); } scanf("%s",s); for(lim = n; lim >= 0; lim--){ if( s[lim] == 'a'+all-1 ) continue; ch0 = -1,ch1 = -1; for(int i = all-1; i > s[lim]-'a'; i--){ if( val[i] == 0) ch0 = 'a'+i; else ch1 = 'a'+i; } if( ch0 == -1 && ch1 == -1 ) continue; ch2 = -1,ch3 = -1; for(int i = all-1; i >= 0; i--){ if( val[i] == 0) ch2 = 'a'+i; else ch3 = 'a'+i; } if( judge() ){ rep(i,n) { if( i < lim ) putchar(s[i]); else{ int u = 2*i; if( i == lim){ if( mark[u] ) putchar(ch0); else putchar(ch1); }else{ if( mark[u] ) putchar(ch2); else putchar(ch3); } } } puts(""); return 0; } } puts("-1"); return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
Codeforces Round #315 (Div. 1) C. New Language(2-sat+贪心)(好题)
标签:
原文地址:http://blog.csdn.net/kalilili/article/details/47832385