//传递闭包 //看了郭老的书才懂得传递闭包的建立 //T为传递闭包数组 //在6中运算关系中,可以简化为<,<=,!= 3中 //a>b ---> b<a //a>=b ---> b<=a //a=b ---> a<=b && b<=a //不等号关系的判断需要另外加入 //为了操作方便,用二进制位压缩来表示变量之间的关系 //T[a][b] = 1 (二进制为01)表示a <= b //T[a][b] = 2 (二进制为10)表示a < b //一、T数组还需要建立初始关系,a<=a //通过这样建立起一个传递闭包后,传递关系的判断就十分容易了 //二、如果T[a][b] = 2 && T[b][a] = 1 || 2 即a<b 且( b >= a 或 b > a)那么就产生冲突 //三、对不等号的的关系另外判断,在NE(not equal)数组中NE[a][b]表示a != b //如果a != b 且 (g[a][b] = 2 或 g[b][a] = 2) 则冲突 #include<iostream> #include<string> #include<map> #include<cstring> using namespace std; map<string,int> M; int T[205][205];//传递闭包数组 int num;//变量数量 int NE[205][2]; int nenum;//不等关系数量 int t = 0,a,b; string var1,var2,op,str; bool solve() { for(int k = 0;k < num;++k) T[k][k] |= 1;//初始状态,k <= k; for(int k = 0;k < num;++k) for(int i = 0;i < num;++i) for(int j = 0;j < num;++j) if(T[i][k] && T[k][j]) T[i][j] |= 1;//求传递闭包 for(int i = 0;i < num;++i) for(int j = 0;j < num;++j) if((T[i][j] & 2) && T[j][i]) return 0; for(int k = 0;k < nenum;++k) { int i = NE[k][0]; int j = NE[k][1]; if((T[i][j] & 1) && (T[j][i] & 1)) return 0; } return 1; } int main() { //freopen("in.txt","r",stdin); num = nenum = 0; cin >> str; while(1) { cin >> var1; if(cin.eof() || var1[var1.size()-1] == ':') { printf("Case%d: ",++t); if(solve()) printf("YES/n"); else printf("NO/n"); if(cin.eof()) break; M.clear(); memset(T,0,sizeof(T)); num = nenum = 0; continue; } else cin >> op >> var2; if(!M.count(var1)) M[var1] = num++; if(!M.count(var2)) M[var2] = num++; a = M[var1]; b = M[var2]; if(op == "<") T[a][b] |= 2; else if(op == "<=") T[a][b] |= 1; else if(op == "=") { T[a][b] |= 1; T[b][a] |= 1; } else if(op == "!=") { NE[nenum][0] = a; NE[nenum++][1] = b; } else if(op == ">=") T[b][a] |= 1; else if(op == ">") T[b][a] |= 2; } return 0; }