• POJ1094 Sorting It All Out (拓扑排序)


    题目链接:http://poj.org/problem?id=1094

    题意:

      给你N个数,和M个关系,你需要通过这M个关系判断能否给这N个数排序,排序的原则类似于“<”运算符,如果a < b, b < c,那么 a < c;顺序的给出这N个数的关系,如果第 k 个关系和之前已经给出的 k-1 个关系矛盾(比如a < b, b < a),那么就输出“Inconsistency found after k relations.”;如果通过第 k 个关系可以确定这N个数的排序序列(比如三个数,两个序列:a < b ,b < c),那么输出“Sorted sequence determined after k relations: yyyyy.”,其中yyyyy是这N个数排序的结果;如果所有的关系给出后,既不矛盾,又不能确定惟一的一个序列(比如三个数,一个序列: a < b),那么就输出“Sorted sequence cannot be determined.”

    思路:

      可以发现着有点类似于拓扑排序,那么这里就用拓扑排序来解决这道题。根据题意建图,如果a<b,那么点 a 到 点 b 就建立一条有向边。这道题需要确定的是一个唯一的序列,所以如果能确定这个序列,那么所建起来的图肯定只有一个入度为0的点,作为这个序列的第一个点,之后删除这个点出发的所有边,然后剩下的图仍然只能有一个入度为零的点以供选取......即每次选择一个点后,然后删除其出发的有向边,剩下的图中只能有一个入度为0的点,才能保证序列唯一,总结下来,满足确定唯一序列的条件是:能对此图所有点进行拓扑排序,且拓扑排序序列唯一。然后需要判断是否成环,如果成环,那么对图运行一次拓扑排序算法之后,剩下的图中应该还有剩余的点,即在某时刻找不到入度为0的点供选择但已经排序的点不足总的点数。最后需要判断是否不能确定这个序列,这个条件只要排除掉上述两种情况就好了,即图中没有环且已经输出了图中的所有点,也就是给出的条件不足以确定这个序列。

    注意:

      如果通过第K个关系已经确定了这个序列,当出现第Z(Z>K)个关系又使得关系矛盾时,不认为其是矛盾的,因为已经确定序列了,就不用去考虑其他条件;反之亦然。

    代码:

     1 #include <iostream>
     2 #include <cmath>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <stack>
     7 #include <queue>
     8 #include <algorithm>
     9 #include <string>
    10 
    11 typedef long long LL;
    12 using namespace std;
    13 const int MAXN = 26;
    14 const int MAXM = 10000;
    15 int indegree[MAXN + 7];//入度
    16 int N, M;
    17 
    18 int head[MAXN + 7];//采用链式前向星存图 
    19 typedef struct EdgeNode {
    20     int to;
    21     int next;
    22 }Edge;
    23 Edge edge[MAXM + 7];
    24 
    25 char ans[MAXN + 7];//答案序列
    26 int len;
    27 int tplgSort() {
    28     int len = 0;
    29     memset(ans, 0, sizeof(ans));
    30     int indg[MAXN + 7] = {0};
    31     for(int i = 0; i <= N; i++) indg[i] = indegree[i];//要进行多次拓扑排序算法,需保留原来的入度数组,新创一个数组进行操作
    32     stack<int> st;//拓扑排序的辅助栈
    33     for(int i = 1; i <= N; i++) {
    34         if(!indg[i]) {//入度为0的进栈
    35             st.push(i);
    36         }
    37     }
    38     int ok = 1;
    39     while(!st.empty()) {    
    40         if((int) st.size() != 1) ok = 0;//每次进栈的数是否仅有一个,即当前图是否仅有一个入度为0的点存在
    41         int tv = st.top();
    42         ans[len++] = tv + 'A' - 1;
    43         st.pop();
    44         for(int k = head[tv]; k != -1; k = edge[k].next) {//选择一个点后,删除从这个点出发的所有有向边
    45             if( !(--indg[edge[k].to]) ) {//删除之后如果入度为0,则进栈
    46                 st.push(edge[k].to);
    47             }
    48         }
    49     }
    50     if(ok == 1 && len == N) return 1;//如果满足每次进栈的数仅有一个且已经生成全部序列,那么就已经确定这个序列了
    51     else {
    52         for(int i = 1; i <= N; i++) {
    53             if(indg[i]) return -1;//如果剩余的图中还有剩余的点(若有剩余的点,则肯定存在入度不为0的点)
    54         }
    55         return 0;//剩余的图中没有点,且未生成全部序列
    56     }
    57 }
    58 
    59 int main() {
    60     //freopen("input", "r", stdin);
    61     //freopen("output", "w", stdout);
    62     while(scanf("%d%d", &N, &M), N || M) {
    63         memset(head, -1, sizeof(head));
    64         memset(&edge, 0, sizeof(EdgeNode));
    65         memset(indegree, 0, sizeof(indegree));
    66         int index = -1, ok = 0;//index标记得出答案的关系号,ok表示当前状态
    67         for(int i = 1; i <= M; i++) {
    68             getchar();
    69             char cu, cv;
    70             cu = getchar(), getchar(), cv = getchar();
    71             int u = cu - 'A' + 1, v = cv - 'A' + 1;
    72             edge[i].to = v; //建图
    73             edge[i].next = head[u];
    74             head[u] = i;
    75             ++indegree[v];
    76             if(ok == 0) ok = tplgSort();//ok=0说明当前关系不能确定唯一序列
    77             if( index < 0 && ok != 0)  index = i;//Ok!=0已经确定唯一序列或者出现矛盾关系,记录下标
    78         }
    79         if(ok == 0) printf("Sorted sequence cannot be determined.
    ");
    80         else if(ok == 1) printf("Sorted sequence determined after %d relations: %s.
    ", index, ans);
    81         else printf("Inconsistency found after %d relations.
    ", index);
    82     }
    83     return 0;
    84 }
  • 相关阅读:
    Pivotal tc Server
    深入剖析jsonp跨域原理
    IE11 el-menu鼠标滑过报错:Error in v-on handler: "TypeError: 对象不支持此操作"
    细嚼JS闭包知识点及案例分析
    关于解决Chrome新版本中cookie跨域携带和samesite的问题处理 ——Ngnix篇
    解决vue本地环境跨域请求正常,版本打包后跨域代理不起作用,请求不到数据的方法——针对vue2.0
    element-ui 的 el-table 上使用无限滚动加载(与自带的 infinite-scroll 结合)——vue2.0
    vue+element-ui table实现滚动加载 ——vue2.0版本
    websocket(一)封装使用
    JS和jQuery将类数组对象转化成数组对象的几种方法
  • 原文地址:https://www.cnblogs.com/Ash-ly/p/5714526.html
Copyright © 2020-2023  润新知