前一阵在看图论时候写的,在光哥题册里发现了拓扑排序这个题,当时搞了一下午,现在记下来,这个题有很多坑。
//============================================================================
//
// > File : poj1094.cpp
// > Author : flowertree
// > Time : 2015年11月5日
// > Algorithm : 拓扑排序(有向无环图的逻辑排序),结合栈或队列实现
// 该题输入恶心复杂,有图不连通和环的情况出现,还可能有重边
// 邻接表实现
// 注意:这个题是进行了N次的拓扑排序,每一次排序会破坏图,
// 所以这个题加入了一些处理,并不是裸的拓扑排序,裸的更简洁
//
//
//============================================================================
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <stack>
#include <queue>
using namespace std;
#define MAX 27 //最大节点数
struct linknode //邻接表的节点
{
char ch;
linknode * next;
};
struct headnode //邻接表的表头
{
int in;
char ch;
linknode * next;
};
headnode head[MAX];
linknode node[MAX * MAX];
char str[MAX]; //存放拓扑排序的结果
bool v[MAX];
int node_count;
int Count;
void Init(int n) //邻接表表头的初始化
{
for(int i = 0; i < n; i++)
{
head[i].in = 0;
head[i].ch = i + 'A';
head[i].next = NULL;
}
}
linknode* getnode() //获取邻接表节点
{
return &node[node_count++];
}
int topologicsort(int n, int sum) //拓扑排序
{
bool mark = false;
Count = 0;
headnode temp;
queue<headnode> q;
linknode * p;
int tempnum;
//创建副本,和排序无关
int d[MAX];
for(int i = 0; i < MAX; i++)
{
d[i] = head[i].in;
}
//找到度为0的头结点
for(int i = 0; i < MAX; i++)
{
if(head[i].in == 0 && v[i] == true)
{
q.push(head[i]);
}
}
//排序核心
while(q.size() != 0)
{
if(q.size() != 1) //与本题有关,与排序无关
{
mark = true;
}
temp = q.front();
q.pop();
str[Count++] = temp.ch;
p = temp.next;
while(p != NULL)
{
tempnum = p -> ch - 'A';
head[tempnum].in--;
if(head[tempnum].in == 0)
{
q.push(head[tempnum]);
}
p = p -> next;
}
}
if(Count != n) //返回矛盾
{
return 1;
}
str[Count] = '\0';
if(Count == sum && mark == false) //排序成功
return 2;
else
{
for(int i = 0; i < MAX; i++) //还原被破坏的图
{
head[i].in = d[i];
}
return 3; //返回无法确定排序顺序或者排序不全
}
}
int main()
{
int m, n, mark, signal, nodesum;
char a, b, c;
int tempa, tempc;
linknode *q;
linknode *p;
bool flag;
while(cin >> m >> n, m && n)
{
memset(v, false, sizeof(v));
nodesum = 0;
signal = 0;
node_count = 0;
Init(m);
for(int i = 0; i < n; i++)
{
getchar();
scanf("%c%c%c", &a, &b, &c);
if(signal != 0)
continue;
tempa = a - 'A';
tempc = c - 'A';
if(v[tempa] == false)
{
v[tempa] = true;
nodesum++;
}
if(v[tempc] == false)
{
v[tempc] = true;
nodesum++;
}
p = head[tempa].next;
if(p == NULL)
{
q = getnode();
q -> ch = c;
head[tempa].next = q;
q -> next = NULL;
}
else
{
flag = false;
if(p -> ch == c)
continue;
while(p -> next != NULL)
{
p = p -> next;
if(p -> ch == c)
{
flag = true;
break;
}
}
if(flag)
{
continue;
}
q = getnode();
q -> ch = c;
p -> next = q;
q -> next = NULL;
}
head[tempc].in++;
//每一次输入一个关系拓扑排序一次
mark= topologicsort(nodesum, m);
if(mark == 1)
{
signal = i + 1;
}
else if(mark == 2)
{
signal = i + 1;
}
}
if(mark == 2)
{
printf("Sorted sequence determined after %d relations: %s.\n", signal, str);
}
else if(mark == 1)
{
printf("Inconsistency found after %d relations.\n", signal);
}
else if(signal == 0)
{
printf("Sorted sequence cannot be determined.\n");
}
}
system("pause");
return 0;
}