第 2 到 N+1 行:每行两个整数 X,Y, 表示 N 个牧区的坐标。每个牧区的坐标都是不一样的。
第 N+2 行到第 2*N+1 行:每行包括 N 个数字 ( 0或1 ) 表示一个对称邻接矩阵。
例如,题目描述中的两个牧场的矩阵描述如下:
A B C D E F G H A 0 1 0 0 0 0 0 0 B 1 0 1 1 1 0 0 0 C 0 1 0 0 1 0 0 0 D 0 1 0 0 1 0 0 0 E 0 1 1 1 0 0 0 0 F 0 0 0 0 0 0 1 0 G 0 0 0 0 0 1 0 1 H 0 0 0 0 0 0 1 0
int n, m; bool g[N][N], d[N][N]; // 表示两个字母之间关系(前一个字母小于后一个字母)是否确定 bool st[N];
voidfloyd() { memcpy(d, g, sizeof d);
for (int k = 0; k < n; k ++ ) for (int i = 0; i < n; i ++ ) for (int j = 0; j < n; j ++ ) d[i][j] |= d[i][k] && d[k][j]; // 如果有i->k k->j的边 那就加上i->j的边 }
intcheck() { for (int i = 0; i < n; i ++ ) if (d[i][i]) return2; // 出现矛盾返回2
for (int i = 0; i < n; i ++ ) for (int j = 0; j < i; j ++ ) if (!d[i][j] && !d[j][i]) return0; // 遍历所有数对 没确定返回0
return1; // 确定就返回1 }
charget_min() { for (int i = 0; i < n; i ++ ) if (!st[i]) { bool flag = true; for (int j = 0; j < n; j ++ ) if (!st[j] && d[j][i]) // 如果有没出现过的j比i还小的话说明i不是最小值 { flag = false; break; } if (flag) // 否则i就是当前没出现过的数中的最小值 { st[i] = true; return'A' + i; } } }
intmain() { while (cin >> n >> m, n || m) { memset(g, 0, sizeof g); int type = 0, t; // type表示目前关系未确定/确定/矛盾 for (int i = 1; i <= m; i ++ ) { char str[5]; cin >> str; int a = str[0] - 'A', b = str[2] - 'A';
if (!type) { g[a][b] = 1; floyd(); type = check(); if (type) t = i; // t记录经过几次才确定所有关系 } }
if (!type) puts("Sorted sequence cannot be determined."); // 关系不确定 elseif (type == 2) cout << "Inconsistency found after " << t << " relations.\n"; // 矛盾 else// 确定 { memset(st, 0, sizeof st); cout << "Sorted sequence determined after " << t << " relations: "; for (int i = 0; i < n; i ++ ) cout << get_min(); cout << ".\n"; } } }