Sorting It All Out--POJ 1094

1、题目类型:图论、拓扑排序。

2、解题思路:(1)每输入一组数据,进行拓扑排序;(2)内部形成环时(即出现冲突)TuoPu()返回-1;内部存在多个入度为0的点时(即无法判断)此时将f标识为1;当拓扑排序正确时,TuoPu()返回排序成功的节点个数;(3)根据TuoPu()的返回值,输出结果,仅当其返回值等于输入N时,结果正确。

3、注意事项:当存在冲突或者拓扑排序成功时,之后的输入不对结果造成影响。

4、实现方法:

#include < iostream >
#include
< queue >
#include
< string >
using namespace std;

int n,m,cnt,f,arr[ 26 ],map[ 26 ][ 26 ];
bool flag[ 26 ],vis[ 26 ];
string str;

// 返回排序成功时内部的元素个数
int TuoPu()
{
int i,j,count = 0 ;
queue
< int > Q;
memset(arr,
0 , sizeof (arr));
memset(flag,
0 , sizeof (flag));
memset(vis,
0 , sizeof (vis));
str
= "" ;
cnt
= 0 ,f = 0 ;
for (i = 0 ;i < 26 ;i ++ )
for (j = 0 ;j < 26 ;j ++ )
if (map[i][j])
{
vis[i]
= 1 ;vis[j] = 1 ;
arr[j]
++ ;
}
// 记录节点的总数
for (i = 0 ;i < 26 ;i ++ )
if (vis[i])
count
++ ;
// 入度为0的入栈
for (i = 0 ;i < 26 ;i ++ )
if ( ! arr[i] && vis[i])
{
flag[i]
= 1 ;
Q.push(i);
}
// 存在环
if (Q.size() == 0 )
return - 1 ;
// 存在多个入度为0的情况,无法判断
else if (Q.size() > 1 )
f
= 1 ;
// 队列内部拓扑判断
while ( ! Q.empty())
{
int tmp = Q.front();
cnt
++ ;
Q.pop();
str
+= tmp + ' A ' ;
for (i = 0 ;i < 26 ;i ++ )
{
if ( ! flag[i] && map[tmp][i] && vis[i])
arr[i]
-- ;
}
int t = 0 ;
for (i = 0 ;i < 26 ;i ++ )
{
if ( ! flag[i] &&! arr[i] && vis[i])
{
flag[i]
= 1 ;
Q.push(i);
t
++ ;
}
}
if (Q.size() == 0 && cnt != count)
return - 1 ;
if (t > 1 )
f
= 1 ;
}
return cnt;
}

int main()
{
char ch1,op,ch2;
int i,mark,pos,tmp;
while (cin >> n >> m)
{
if (n == 0 && m == 0 )
break ;
memset(map,
0 , sizeof (map));
mark
= 0 ;
for (i = 0 ;i < m;i ++ )
{
cin
>> ch1 >> op >> ch2;
map[ch1
- ' A ' ][ch2 - ' A ' ] = 1 ;
// 没有找到且没有出错
if (mark == 0 )
{
tmp
= TuoPu();
if (tmp ==- 1 )
{
pos
= i + 1 ;
mark
= 1 ;
}
else if (tmp ==- 2 )
continue ;
else if (tmp == n && f == 0 )
{
pos
= i + 1 ;
mark
= 2 ;
}
}
}
if (mark == 2 && f == 0 )
cout
<< " Sorted sequence determined after " << pos << " relations: " << str << " . " << endl;
else if (mark == 1 )
cout
<< " Inconsistency found after " << pos << " relations. " << endl;
else
cout
<< " Sorted sequence cannot be determined. " << endl;
}
return 0 ;
}

转载于:https://www.cnblogs.com/yongze103/archive/2010/08/09/1796070.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值