poj 1094 之解法二 拓扑排序

题目链接

题意:给出大于等于 A 小于 A +  n 的字母间的大小关系式,问是否能确定 n个字母的大小关系?如能,在第几个关系式时能确定?如不能,是否出现了矛盾,在第几个关系式时出现了矛盾?

关系式举例如下:

A<B
A<C
B<C
C<D
B<D
A<B
#include<stdio.h>
#include <stdlib.h>
#include <iostream>
#include<string>
using namespace std;
int n, flag;
int result[27];      //拓扑排序结果存放数组
int visited[27];     //拓扑排序时标识是否已访问过
int map[27][27];     //map[i][j] = 1 表示从 i + 'A' 到 j + 'A' 之间有一条单向边
int in[27];          //in[i] 存放 i + 'A' 的入度

/检查是否有环
void floyd( int a, int b ){
	int i, j, k;
	for( k = 0; k < n; k ++ ){
		for( i = 0; i < n; i ++ ){
			for( j = 0; j < n; j ++ ){
				if( map[i][k] == 1 && map[k][j] == 1 ){
					if( map[i][j] == 0 ){
						map[i][j] = 1;
						in[j] ++;     //注意入度的更新
					}
					if( i == a && j == b ){
						//发现有环
						flag = 1;
						return;			
					}
				}
			}
		}
	}
}
拓扑排序
bool Toposort( ){
	int i, j, k, size = 0;	
	bool remark;
	int tmp[27];    //入度的副本
	for( i = 0; i < 26; i ++ )
		tmp[i] = in[i];
	for( i = 0; i < n; i ++ ){
		k = -1;
		remark = false;
		for( j = 0; j < n; j ++ ){			
			if( tmp[j] == 0 && !visited[j] ){
				if( remark )		//入度为0的节点超过两个表示拓扑排序结果不唯一
					return false;     
				remark = true;
				k = j;
			}
		}
		if( k == -1 )
			return false;
		result[size ++] = k;
		visited[k] = 1;

		更新有从已排序的当前节点有单向边的节点的入度
		for( j = 0; j < n; j ++ ){	
			if( map[k][j] == 1 )
				tmp[j] --;
		}
	}
	return true;
}
int main()
{
	int  m, i, j;
	//freopen("C:\\Users\\Administrator\\Desktop\\cincout\\1.txt", "r", stdin);
	//freopen("C:\\Users\\Administrator\\Desktop\\cincout\\2.txt", "w", stdout);
	while( scanf("%d%d", &n, &m ) && ( n || m ) ){	
		memset( map, 0, sizeof( map ) );
		memset( in, 0, sizeof( in ) );
		flag = 0;
		char a, b;
		for( i = 1; i <= m; i ++ ){
			string s;
			cin>>s;
			a = s[0]; b = s[2];
			if( flag == 0 ){
				if( map[a - 'A'][b - 'A'] == 0 ){
					map[a - 'A'][b - 'A'] = 1;
					in[b - 'A'] ++;
				}

	            检查是否有矛盾,即对环的检查
				floyd( b - 'A', a - 'A' );
				if( flag == 1 )
					printf( "Inconsistency found after %d relations.\n", i );	
				
				else{
						memset( visited, 0, sizeof( visited ) );
						if( Toposort() ){
							printf( "Sorted sequence determined after %d relations: ", i );
							for( j = 0; j < n; j ++ )
								printf("%c", result[j] + 'A');
							printf(".\n");		
							flag = 1;
						}
				}
			}
		}									
		if( flag == 0 )
			printf("Sorted sequence cannot be determined.\n");	
	}
	//fclose(stdin);
	//fclose(stdout);	
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值