main
黄海 2 years ago
parent 2eeb4fa09b
commit a720cef8e4

@ -171,28 +171,30 @@ string getorder(){
#include <bits/stdc++.h> #include <bits/stdc++.h>
using namespace std; using namespace std;
// Floyd解决传送闭包问题 const int N = 26;
const int N = 27;
int n; // n个变量
int m; // m个不等式
int f[N][N]; // 传递闭包结果
int n, m;
int g[N][N];
bool st[N];
// 求传递闭包
void floyd() { void floyd() {
for (int k = 0; k < n; k++) for (int k = 0; k < n; k++)
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) for (int j = 0; j < n; j++)
f[i][j] |= f[i][k] & f[k][j]; // i可以到达k,k可以到达j,那么i可以到达j g[i][j] |= g[i][k] && g[k][j];
} }
// 1:可以确定两两之间的关系,2:矛盾,3:不能确定两两之间的关系
int check() { int check() {
// 如果i<i
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
if (f[i][i]) return 2; if (g[i][i]) return 2; // 矛盾
// 存在还没有识别出关系的两个点i,j,还要继续读入
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++) for (int j = 0; j < i; j++)
if (!f[i][j] && !f[j][i]) return 3; if (!g[i][j] && !g[j][i]) // 待继续
return 1; return 0;
return 1; // 找到顺序
} }
string getorder() { // 升序输出所有变量 string getorder() { // 升序输出所有变量
@ -200,46 +202,46 @@ string getorder() { // 升序输出所有变量
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
int cnt = 0; int cnt = 0;
// f[i][j] = 1表示i可以到达j (i< j) // f[i][j] = 1表示i可以到达j (i< j)
for (int j = 0; j < n; j++) cnt += f[i][j]; // i for (int j = 0; j < n; j++) cnt += g[i][j]; // i
// 举个栗子i=0,表示字符A // 举个栗子i=0,表示字符A
// 比如比i大的有5个共6个字符ABCDEF // 比如比i大的有5个共6个字符ABCDEF
// n - cnt - 1 = 6-5-1 = 0,也就是A放在第一个输出的位置上, 之所以再-1是因为下标从0开始 // n - cnt - 1 = 6-5-1 = 0,也就是A放在第一个输出的位置上, 之所以再-1是因为下标从0开始
s[n - cnt - 1] = i + 'A'; s[n - cnt - 1] = i + 'A';
} }
// 转s字符数组为字符串
return string(s, s + n); // 转s字符数组为字符串
string res;
for (int i = 0; i < n; i++) res = res + s[i];
return res;
} }
int main() { int main() {
// n个变量,m个不等式 while (cin >> n >> m, n || m) {
// 当输入一行 0 0 时,表示输入终止 memset(g, 0, sizeof g); // 邻接矩阵
while (cin >> n >> m, n && m) { int type = 0, t; // type: 0=还需要继续给出条件 1=找到了顺序 2=存在冲突
string S; // t:在第几次输入后找到了顺序不能中间break,因为那样会造成数据无法完成读入后续的操作无法进行只能记录下来当时的i
int k = 3; // 3:不能确定两两之间的关系
memset(f, 0, sizeof f); // 初始化邻接矩阵
// m条边
for (int i = 1; i <= m; i++) { for (int i = 1; i <= m; i++) {
cin >> S; char s[5];
// 已确定或者出现了矛盾,就没有必要再处理了,但是,还需要耐心的读取完毕,因为可能还有下一轮,不读入完耽误下一轮 cin >> s;
if (k < 3) continue; int a = s[0] - 'A', b = s[2] - 'A'; // A->0,B->1,...,Z->25完成映射关系
// 变量只可能为大写字母A~Z,映射到0~25
int a = S[0] - 'A', b = S[2] - 'A'; if (!type) { // 如果不存在矛盾,就尝试找出大小的顺序
f[a][b] = 1; // 记录a<b g[a][b] = 1; // 有边
floyd(); // 求传递闭包
// 每输入一个关系,就计算一遍传递闭包 type = check(); // 检查是不是存在矛盾,或者找到了完整的顺序
floyd(); if (type > 0) t = i; // 如果找到了顺序,或者发现了矛盾,记录是第几次输入后发现的
// 检查一下现在的情况,是不是已经可以判定了
k = check();
if (k == 2) // 出现矛盾
printf("Inconsistency found after %d relations.\n", i);
else if (k == 1) { // 可以确定
string ans = getorder(); // 输出升序排列的所有变量
printf("Sorted sequence determined after %d relations: %s.\n", i, ans.c_str());
} }
// 即使存在矛盾,也需要继续读入,直到本轮数据读入完成
}
if (!type)
puts("Sorted sequence cannot be determined.");
else if (type == 2)
printf("Inconsistency found after %d relations.\n", t);
else {
string ans = getorder(); // 输出升序排列的所有变量
printf("Sorted sequence determined after %d relations: %s.\n", t, ans.c_str());
} }
// 所有表达式都输入了,仍然定不下来关系
if (k == 3) printf("Sorted sequence cannot be determined.\n");
} }
return 0; return 0;
} }

@ -38,8 +38,11 @@ string getorder() { // 升序输出所有变量
// n - cnt - 1 = 6-5-1 = 0,也就是A放在第一个输出的位置上, 之所以再-1是因为下标从0开始 // n - cnt - 1 = 6-5-1 = 0,也就是A放在第一个输出的位置上, 之所以再-1是因为下标从0开始
s[n - cnt - 1] = i + 'A'; s[n - cnt - 1] = i + 'A';
} }
// 转s字符数组为字符串
return string(s, s + n); // 转s字符数组为字符串
string res;
for (int i = 0; i < n; i++) res = res + s[i];
return res;
} }
int main() { int main() {

@ -4,39 +4,41 @@ using namespace std;
const int N = 26; const int N = 26;
int n, m; int n, m;
bool d[N][N]; bool g[N][N];
bool st[N]; bool st[N];
int check() { int check() {
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
if (d[i][i]) return 2; if (g[i][i]) return 2;
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++) for (int j = 0; j < i; j++)
if (!d[i][j] && !d[j][i]) return 0; if (!g[i][j] && !g[j][i]) return 0;
return 1; return 1;
} }
char get_min() { string getorder() { // 升序输出所有变量
for (int i = 0; i < n; i++) char s[26];
if (!st[i]) { for (int i = 0; i < n; i++) {
bool flag = true; int cnt = 0;
for (int j = 0; j < n; j++) // f[i][j] = 1表示i可以到达j (i< j)
if (!st[j] && d[j][i]) { for (int j = 0; j < n; j++) cnt += g[i][j]; // 比i大的有多少个
flag = false; // 举个栗子i=0,表示字符A
break; // 比如比i大的有5个共6个字符ABCDEF
} // n - cnt - 1 = 6-5-1 = 0,也就是A放在第一个输出的位置上, 之所以再-1是因为下标从0开始
if (flag) { s[n - cnt - 1] = i + 'A';
st[i] = true; }
return 'A' + i;
} // 转s字符数组为字符串
} string res;
for (int i = 0; i < n; i++) res = res + s[i];
return res;
} }
int main() { int main() {
while (cin >> n >> m, n || m) { while (cin >> n >> m, n || m) {
memset(d, 0, sizeof d); memset(g, 0, sizeof g);
int type = 0, t; int type = 0, t;
for (int i = 1; i <= m; i++) { for (int i = 1; i <= m; i++) {
@ -45,13 +47,13 @@ int main() {
int a = str[0] - 'A', b = str[2] - 'A'; int a = str[0] - 'A', b = str[2] - 'A';
if (!type) { if (!type) {
d[a][b] = 1; g[a][b] = 1;
for (int x = 0; x < n; x++) { for (int x = 0; x < n; x++) {
if (d[x][a]) d[x][b] = 1; if (g[x][a]) g[x][b] = 1;
if (d[b][x]) d[a][x] = 1; if (g[b][x]) g[a][x] = 1;
for (int y = 0; y < n; y++) for (int y = 0; y < n; y++)
if (d[x][a] && d[b][y]) if (g[x][a] && g[b][y])
d[x][y] = 1; g[x][y] = 1;
} }
type = check(); type = check();
if (type) t = i; if (type) t = i;
@ -63,10 +65,8 @@ int main() {
else if (type == 2) else if (type == 2)
printf("Inconsistency found after %d relations.\n", t); printf("Inconsistency found after %d relations.\n", t);
else { else {
memset(st, 0, sizeof st); string ans = getorder(); // 输出升序排列的所有变量
printf("Sorted sequence determined after %d relations: ", t); printf("Sorted sequence determined after %d relations: %s.\n", t, ans.c_str());
for (int i = 0; i < n; i++) printf("%c", get_min());
printf(".\n");
} }
} }

Loading…
Cancel
Save