AcWing 343. 排序
原题链接
简单
排序
- 这道题其实就是求传递闭包。
- 在这道题里面在求出传递闭包之后要进行判断
- 首先如果发现有 $d(i,i)=1$ ,也就是
i<i
的话,说明这个序列一定是不合法的。
- 如果发现 $d(i,j)=1$ 而且 $d(i,j)=0$ 的话,可以说明这个序列一定是合法的。
- 如果在处理完所有序列之后还是不能完全确定某一个 $d(i,j)$ 的值,说明这个序列是不确定的。
- 在求最小值的时候用了有点类似拓扑排序的方法。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
const int N = 26;
int n, m;
bool g[N][N], d[N][N];
bool st[N];
void floyd()
{
memcpy(d, g, sizeof g);
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];
}
int check()
{
// 首先判断i<i是否会发生。如果会发生的话说明不合法。
for (int i = 0; i < n; i ++ )
if (d[i][i])
return 2;
// 如果g(i,j)和g(j,i)均为0,说明还没得到正确的结果
for (int i = 0; i < n; i ++ )
for (int j = i + 1; j < n; j ++ )
if (!d[i][j] && !d[j][i])
return 0;
return 1;
}
int get_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没有被用过而且j大于i
{
flag = false;
break;
}
// 找到了当前最小的数字
if (flag)
{
st[i] = true;
return 'A' + i;
}
}
// 不可能执行
return -1;
}
int main()
{
while (cin >> n >> m, n || m)
{
memset(g, false, sizeof g);
memset(d, false, sizeof d);
memset(st, false, sizeof st);
int type = 0, t = -1;
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] = true;
floyd();
type = check();
if (type) t = i;
}
}
if (!type) puts("Sorted sequence cannot be determined.");
else if (type == 2) printf("Inconsistency found after %d relations.\n", t);
else
{
memset(st, false, sizeof st);
printf("Sorted sequence determined after %d relations: ", t);
for (int i = 0; i < n; i ++ ) printf("%c", get_min());
puts(".");
}
}
return 0;
}