poj 1094 拓扑排序

前一阵在看图论时候写的,在光哥题册里发现了拓扑排序这个题,当时搞了一下午,现在记下来,这个题有很多坑。

//============================================================================
//
// >     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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值