• POJ- 1094 Sorting It All Out---拓扑排序是否唯一的判断


    题目链接:

    https://vjudge.net/problem/POJ-1094

    题目大意:

    该题题意明确,就是给定一组字母的大小关系判断他们是否能组成唯一的拓扑序列。是典型的拓扑排序,但输出格式上确有三种形式:

       1.该字母序列有序,并依次输出;

       2.该序列不能判断是否有序(序列不唯一);

       3.该序列字母次序之间有矛盾,即有环存在。

    思路:

    这里应该用Kahn算法拓扑排序

    每加入一条边需要进行一次拓扑排序,如果拓扑排序发现有环,或者排序唯一那么就可以直接输出结果,如果所有的边输入完成还不是上述两种情况,那就输出不能判断。

    这里的重点在于如何判断拓扑排序的唯一性,这里运用了Kahn算法的思想。

    Kahn算法:

    1.找到入度为0的顶点加入栈中,然后提出栈顶元素,成为拓扑排序的一部分

    2.除去与之相邻所有边并减少其度数,再次加入入度数为0的点循环往复,如果某一次栈已经空了而且没有入读为0的点,那就是存在有向环。

    判断唯一性:

    那就得每次找到入度为0的顶点个数只能是1个,是0个说明存在环,多个说明拓扑排序不唯一。

    由于每次只能有一个0度顶点,所以可以循环n次,依次找出拓扑排序中的每一位

    需要注意的是,如果有一次找出了多个0度顶点,不能直接返回无序,只能暂时标记,因为可能之后的循环中存在环。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #include<stack>
     8 #include<map>
     9 #include<set>
    10 #include<sstream>
    11 #include<functional>
    12 using namespace std;
    13 typedef long long ll;
    14 const int maxn = 100 + 10;
    15 const int INF = 1e9 + 7;
    16 int T, n, m, cases;
    17 vector<int>Map[maxn];
    18 int Count[maxn];
    19 int ans[maxn];
    20 int topo()
    21 {
    22     int cnt[maxn];
    23     memcpy(cnt, Count, sizeof(Count));
    24     int flag = 1;
    25     for(int i = 0; i < n; i++)//为判断顺序是否唯一,有序的顺序拓扑排序需要n次循环
    26     {
    27         int tot = 0;//度数为0的顶点的个数,超过一个说明拓扑排序一定不是唯一,可能不能确定,可能有环
    28         int u;//记录度数为0的点
    29         for(int j = 0; j < n; j++)if(cnt[j] == 0){tot++, u = j;}
    30         if(tot == 0)return 0;//有环
    31         if(tot > 1)flag = -1;//一定不唯一,但是不能立马退出,因为之后有可能是有环
    32         ans[i] = u;//记录拓扑排序顺序
    33         cnt[u] = -1;//已经排好,设成负数
    34         for(int j = 0; j < Map[u].size(); j++)
    35         {
    36             int v = Map[u][j];
    37             cnt[v]--;
    38         }
    39     }
    40     return flag;
    41 }
    42 int main()
    43 {
    44     while(cin >> n >> m)
    45     {
    46         if(!n && !m)break;
    47         string s;
    48         int flag = 0;
    49         for(int i = 0; i <= n; i++)Map[i].clear();
    50         memset(Count, 0, sizeof(Count));
    51         for(int i = 1; i <= m; i++)
    52         {
    53             cin >> s;
    54             int u = s[0] - 'A';
    55             int v = s[2] - 'A';
    56             Map[u].push_back(v);
    57             Count[v]++;//入度
    58             if(flag)continue;//如果已经判断出有序或者有环,就不做处理
    59             int t = topo();
    60             //cout<<t<<endl;
    61             if(t == 0)//有环
    62             {
    63                 printf("Inconsistency found after %d relations.
    ",i);
    64                 flag = 1;
    65             }
    66             if(t == 1)//有序
    67             {
    68                 printf("Sorted sequence determined after %d relations: ",i);
    69                 for(int i = 0; i < n; i++)printf("%c", ans[i] + 'A');
    70                 printf(".
    ");
    71                 flag = 1;
    72             }
    73         }
    74         if(!flag)printf("Sorted sequence cannot be determined.
    ");
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    SQL GROUPING 运算符
    SQL 中各种各样的函数
    SQL 窗口函数简介
    [OpenWrt] 简单的策略路由
    简略讲解OpenWrt的路由配置(单播路由/静态路由、策略路由、IGMP组播路由)
    WPF中XAML中使用String.Format格式化字符串示例
    链接服务器使用OPENQUERY性能提升
    VSCode中不能使用cnpm的解决方案
    SQL执行时间计算常用的两种方法
    C# 实现简体中文和繁体中文的转换
  • 原文地址:https://www.cnblogs.com/fzl194/p/8748122.html
Copyright © 2020-2023  润新知