/*
思路:典型的拓扑排序问题
这道题题意容易引起误解:
如果解不唯一,则输出Sorted sequence cannot be determined.
如果存在环,则输出Inconsistency found after %d relations.
如果解唯一,则输出Sorted sequence determined after %d relations: %s.
*/
#include <iostream>
using namespace std;
const int MAX_NUM = 32;
int map[MAX_NUM][MAX_NUM];
bool vis[MAX_NUM]; //记录到目前为止在输入中出现的顶点
int count[MAX_NUM]; //保存每个顶点的入度
int buf[MAX_NUM];
char res[MAX_NUM];
int n, m;
bool single_solution;
int topo_order()
{
int i, j, k, top = -1, cnt = 0, vetex_num = 0;
single_solution = true; //是否是唯一解
for (i = 0; i < n; ++i){
if (vis[i]){
vetex_num++;
if (count[i] == 0){ //用count数组模拟堆栈,数组的下标是要压栈的数值
count[i] = top;
top = i;
}
}
}
for (i = 0; i < vetex_num; ++i){
if (top == -1){ //不存在入度为0的点,说明存在环
return 0;
}
else{
j = top;
top = count[top];
if (top != -1){
single_solution = false; //存在其他入度为0的点,说明解不唯一
}
res[cnt++] = char('A' + j);
//将该点去掉,并且对于所有以该点为起点的边,边的终点入度都减1
for (k = 0; k < n; ++k){
if (map[j][k] && (--count[k]) == 0){
count[k] = top;
top = k;
}
}
}
}
res[cnt] = '\0';
return cnt;
}
int main()
{
int i, j, from, to, flag, step;
char s[6];
while (scanf("%d%d", &n, &m) && n != 0){
flag = n - 1;
step = -1;
single_solution = false;
memset(count, 0, sizeof(count));
memset(buf, 0, sizeof(buf));
memset(vis, 0, sizeof(vis));
memset(map, 0, sizeof(map));
for (i = 1; i <= m; ++i){
scanf("%s", s);
//如果存在环或者解唯一,则忽略输入
if (flag == 0 || (flag == n && single_solution)){
continue;
}
memcpy(count, buf, sizeof(count));
from = s[0] - 'A';
to = s[2] - 'A';
count[to]++;
map[from][to] = 1;
vis[from] = vis[to] = true;
memcpy(buf, count, sizeof(count));
flag = topo_order();
if (flag == 0 || (flag == n && single_solution)){
step = i;
}
//step = i; // 记录步数
}
if (flag == 0){
printf("Inconsistency found after %d relations.\n", step);
}
else if (flag == n && single_solution){
printf("Sorted sequence determined after %d relations: %s.\n", step, res);
}
else{
printf("Sorted sequence cannot be determined.\n");
}
}
return 0;
}
POJ 1094(拓扑排序)
最新推荐文章于 2020-03-04 17:49:32 发布