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 ;
}
#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 ;
}