AcWing 排序
Description
给定 n 个变量,m 个不等式。
不等式之间具有传递性,即若 A>B 且 B>C ,则 A>C。
判断这 m 个不等式是否有矛盾。
若存在矛盾,则求出 t 的最小值,满足仅用前 t 个不等式就能确定不等式之间存在矛盾。
若无矛盾,则判断这 m 个不等式是否能确定每一对变量之间的关系。
若能,则求出 t 的最小值,满足仅用前 t 个不等式就能确定每一对变量之间的大小关系。
Input
输入包含多组测试数据。
每组测试数据,第一行包含两个整数n和m。
接下来m行,每行包含一个不等式,不等式全部为小于关系。
当输入一行0 0时,表示输入终止。
Output
每组数据输出一个占一行的结果。
结果可能为下列三种之一:
1、”Sorted sequence determined after t relations: yyy…y.”,其中yyy…y是指升序排列的所有变量。
2、”Sorted sequence cannot be determined.”。
3、”Inconsistency found after t relations.”。
Data Size
- 2≤n≤26,变量只可能为大写字母A~Z。
Sample Input
4 6 A<B A<C B<C C<D B<D A<B 3 2 A<B B<A 26 1 A<Z 0 0
Sample Output
Sorted sequence determined after 4 relations: ABCD. Inconsistency found after 2 relations. Sorted sequence cannot be determined.
题解:
- Floyd / 拓扑排序。
- 这题显然是个传递闭包的题,先将i < j写成f(i, j) = 1。然后用Flyod传递下闭包。传完后两层循环枚举i和j,若存在f(i, j)和f(j, i)都为1,说明矛盾。若f(i, j)和f(j, i)都为0,说明不能确定。然后最早确定的位置可以用二分。
- 嘛但是我试着写了拓扑。
- 首先i<j的话,连一条i到j的边。显然关系确定的话一定是一条链。那么每加入一组关系,做一次拓扑。如果有环,直接返回矛盾。在拓扑函数内部中,每轮如果队列中出现有>1个点,说明不能确定。最后做完拓扑后,说明是可以确定且无矛盾的,再若涉及到的点已经是全部点,就返回可以。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#define N 105
using namespace std;
struct E {int next, to;} e[100005];
int n, m, num;
int h[N], in[N], t[N], seq[N];
bool vis[N], tag[N];
bool rel[N][N];
vector<int> a;
void add(int u, int v)
{
e[++num].next = h[u];
e[num].to = v;
h[u] = num;
}
int topsort()
{
queue<int> que;
int flag = 0, cnt = 0;
for(int i = 1; i <= 26; i++) t[i] = in[i];
for(int i = 0; i < a.size(); i++)
if(!in[a[i]]) que.push(a[i]);
while(que.size())
{
if(que.size() > 1) flag = 1;
int now = que.front(); que.pop();
seq[++cnt] = now;
for(int i = h[now]; i != 0; i = e[i].next)
{
in[e[i].to]--;
if(!in[e[i].to]) que.push(e[i].to);
}
}
for(int i = 1; i <= 26; i++) in[i] = t[i];
if(cnt != a.size()) return -1;
if(!flag && cnt == n) return 1;
else return 0;
}
void ini()
{
a.clear(), num = 0;
memset(h, 0, sizeof(h));
memset(vis, 0, sizeof(vis));
memset(in, 0, sizeof(in));
memset(rel, 0, sizeof(rel));
}
int main()
{
while(scanf("%d%d", &n, &m) == 2)
{
if(!n && !m) break;
ini();
for(int i = 1; i <= m; i++)
{
char c[6]; scanf("%s", c);
int u = c[0] - 'A' + 1, v = c[2] - 'A' + 1;
if(!rel[u][v])
{
rel[u][v] = 1;
if(!vis[u]) vis[u] = 1, a.push_back(u);
if(!vis[v]) vis[v] = 1, a.push_back(v);
add(u, v), in[v]++;
}
int ans = topsort();
if(ans == -1)
{
printf("Inconsistency found after %d relations.\n", i);
for(int j = i + 1; j <= m; j++) scanf("%s", c);
break;
}
else if(!ans && i == m) printf("Sorted sequence cannot be determined.\n");
else if(ans == 1)
{
printf("Sorted sequence determined after %d relations: ", i);
for(int j = 1; j <= n; j++) printf("%c", (char)(seq[j] - 1 + 'A'));
printf(".\n");
for(int j = i + 1; j <= m; j++) scanf("%s", c);
break;
}
}
}
return 0;
}