题意:
见http://www.nocow.cn/index.php/Translate:Sgu/161
分析:
①看不懂题没关系,多看几遍...
②注意翻译中的(E1 == E2) ∧ (E2 == E3) ∧ ... ∧ (E(n-1) == En),原题中是 (E1 == E2) ∧ (E2 == E3) ∧ ... ∧ (E(n-1) => En)
而我要说的是,翻译对了,原题错了...
③预处理两两之间的运算,然后就跟表达式求值类似了。
④考验代码能力的题(不过也有可能是我太弱了...),反正注意细节就好了。
见http://www.nocow.cn/index.php/Translate:Sgu/161
分析:
①看不懂题没关系,多看几遍...
②注意翻译中的(E1 == E2) ∧ (E2 == E3) ∧ ... ∧ (E(n-1) == En),原题中是 (E1 == E2) ∧ (E2 == E3) ∧ ... ∧ (E(n-1) => En)
而我要说的是,翻译对了,原题错了...
③预处理两两之间的运算,然后就跟表达式求值类似了。
④考验代码能力的题(不过也有可能是我太弱了...),反正注意细节就好了。
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 110, MAXL = 300;
int n, m;
bool g[MAXN][MAXN] = {0};
struct MH{bool in[MAXN];}tmpp, O = {{0}}, full;
int zero, one;
int _and[MAXN][MAXN], _or[MAXN][MAXN], _im[MAXN][MAXN];
MH H[MAXN];
int lim;
//()!&|>=
int symbol[250];
bool order[8][8] =
{
1,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,
1,1,0,0,1,1,1,1,
1,1,0,0,0,1,1,1,
1,1,0,0,0,1,1,1,
1,1,0,0,0,0,1,1,
0,0,0,0,0,0,0,0
};
void make_symbol()
{
symbol['('] = 0;
symbol[')'] = 1;
symbol['~'] = 2;
symbol['&'] = 3;
symbol['|'] = 4;
symbol['>'] = 5;
symbol['='] = 6;
symbol['#'] = 7;
}
void find_H(int cur)
{
if(cur == n)
{
H[lim++] = tmpp;
return ;
}
find_H(cur+1);
for(int i = 0; i < cur; ++i)
if(tmpp.in[i] && (g[i][cur] || g[cur][i]))
return ;
tmpp.in[cur] = 1;
find_H(cur+1);
tmpp.in[cur] = 0;
}
MH MAX(const MH &X)
{
MH Y = O;
for(int i = 0; i < n; ++i)
{
if(X.in[i])
{
bool flag = 1;
for(int j = 0; j < n; ++j)
if(X.in[j] && i != j)
if(g[i][j])
{
flag = 0;
break;
}
if(flag)
Y.in[i] = 1;
}
}
return Y;
}
MH operator > (const MH &A, const MH &B)
{
MH re = O;
for(int i = 0; i < n; ++i)
if(B.in[i])
{
bool flag = 1;
for(int j = 0; j < n; ++j)
if(A.in[j])
if(g[i][j])
{
flag = 0;
break;
}
if(flag)
re.in[i] = 1;
}
return re;
}
MH operator & (const MH &A, const MH &B)
{
MH re = O;
for(int i = 0; i < n; ++i)
if(A.in[i] || B.in[i])
re.in[i] = 1;
return MAX(re);
}
MH operator | (const MH &A, const MH &B)
{
MH re = O;
for(int i = 0; i < n; ++i)
{
bool y = 0, z = 0;
for(int j = 0; j < n; ++j)
if(A.in[j] && g[i][j])
{
y = 1;
break;
}
if(!y) continue;
for(int j = 0; j < n; ++j)
if(B.in[j] && g[i][j])
{
z = 1;
break;
}
if(z)
re.in[i] = 1;
}
return MAX(re);
}
char str[MAXL] = "\0";
bool hash[30] = {0};
int point[30] = {0};
int var[30] = {0};
int sumv = 0;
int len = 0;
bool ans = 1;
bool check()
{
int tmp;
int X[MAXL] = {0};
int L[MAXL] = {0};
int top1 = 0, top2 = 0;
for(int i = 0; i < len; ++i)
if(str[i] == '0')
X[top1++] = zero;
else if(str[i] == '1')
X[top1++] = one;
else if(str[i] >= 'A' && str[i] <= 'Z')
X[top1++] = var[point[str[i]-'A']];
else
{
int u = symbol[(int)str[i]];
while(top2 && !order[u][L[top2-1]])
{
if(u == 1 && L[top2-1] == 0)
{
top2--;
break;
}
if(L[top2-1] == 6)
{
int v = 0, xv;
for(; L[top2-v-1] == 6; ++v);
top2 -= v;
xv = top1-v-1;
tmp = _and[_im[X[xv]][X[xv+1]]][_im[X[xv+1]][X[xv]]];
for(++xv; xv < top1-1; ++xv)
tmp = _and[tmp][_and[_im[X[xv]][X[xv+1]]][_im[X[xv+1]][X[xv]]]];
top1 -= v;
X[top1-1] = tmp;
continue;
}
top2--;
if(L[top2] == 5)
X[top1-2] = _im[X[top1-2]][X[top1-1]];
else if(L[top2] == 4)
X[top1-2] = _or[X[top1-2]][X[top1-1]];
else if(L[top2] == 3)
X[top1-2] = _and[X[top1-2]][X[top1-1]];
else if(L[top2] == 2)
{
X[top1-1] = _im[X[top1-1]][zero];
continue;
}
top1--;
}
if(u != 1) L[top2++] = u;
}
return !X[0];
}
bool dfs(int cur)
{
if(cur == sumv)
return check();
for(int i = 0; i < lim; ++i)
{
var[cur] = i;
if(!dfs(cur+1)) return 0;
var[cur] = 0;
}
return 1;
}
void solve()
{
memset(str, '\0', sizeof(str));
memset(hash, 0, sizeof(hash));
memset(point, 0, sizeof(point));
memset(var, 0, sizeof(var));
sumv = len = 0;
ans = 1;
str[len++] = '#';
for(;;)
{
char c;
if(scanf("%c", &c) == EOF) break;
if(c == '\n') break;
if(c == ' ') continue;
if(c == '>') str[len-1] = '>';
else str[len++] = c;
if(c >= 'A' && c <= 'Z') hash[c-'A'] = 1;
}
str[len++] = '#';
for(int i = 0; i < 26; ++i)
if(hash[i])
point[i] = sumv++;
if(dfs(0)) puts("valid");
else puts("invalid");
}
bool operator == (const MH &A, const MH &B)
{
for(int i = 0; i < n; ++i)
if(A.in[i] != B.in[i]) return 0;
return 1;
}
int find(const MH &P)
{
for(int i = 0; i < lim; ++i)
if(P == H[i]) return i;
}
void pre_calc()
{
for(int i = 0; i < lim; ++i)
for(int j = 0; j < lim; ++j)
{
_and[i][j] = find(H[i]&H[j]);
_or[i][j] = find(H[i]|H[j]);
_im[i][j] = find(H[i]>H[j]);
}
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 0; i < m; ++i)
{
int u, v;
scanf("%d%d", &u, &v);
g[--u][--v] = 1;
}
for(int k = 0; k < n; ++k)
for(int i = 0; i < n; ++i)
for(int j = 0; j < n; ++j)
if(g[i][k] && g[k][j])
g[i][j] = 1;
for(int i = 0; i < n; ++i)
g[i][i] = 1;
find_H(0);
memset(full.in, 1, sizeof(full.in));
zero = find(MAX(full));
one = find(O);
make_symbol();
pre_calc();
int K = 0;
scanf("%d\n", &K);
while(K--)
solve();
return 0;
}