POJ1904 Sorting It All Out 拓扑排序

该题在给定了一些大小的关系的基础上询问是否可以断定N个数的大小关系,其实就是一个拓扑排序题。

注意题义是在给定M组关系中依次处理,一旦根据1-K(1<=K<=N)能够判定是否确定或者冲突则马上退出来。如果一直到最后一组数据还没有这两种情况的话就是不能确定了。

两重for循环建立边的关系,用来完成题目中要求的依次处理,对于每一种情况进行一次拓扑排序,查看是否成环或者确定关系。

  成环的判定方式当每次从所有点中选取度为零的节点不能够再进行的时候,此时选取出来的点还没有N个则说明有环的存在;

  如果所有的点都能够被取出来并且在整个取的过程中每次都有且尽有1个度为零的节点,那么就说明关系可以确定;

  否则为不确定

代码如下:

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <list>
#include <stack>
#include <cctype>
#include <iostream>
using namespace std;

int N, M, pos, rec[10000][2], path[30], cnt;

struct Edge
{
    int no, next;
}e[10000];

struct Node
{
    int de, next;
}p[30];

void insert(int x, int y)
{
    ++pos;
    e[pos].no = y;
    e[pos].next = p[x].next;
    p[x].next = pos;
    ++p[y].de;
}

void init()
{
    pos = cnt = 0;
    for (int i = 1; i <= N; ++i) {
        p[i].next = 0;  // 设置结束标志
        p[i].de = 0;
    }
}

int fzde(bool &nuc)
{
    int flag = 0, ans = 0;
    for (int i = 1; i <= N; ++i) {
        if (p[i].de == 0) {
            if (!flag) {
                flag = 1;
                ans = i;
            }
            else {
                nuc = true;
                break;
            }
        }
    }
    return ans;
}

int topology()
{
    int node = 0;
    bool nuc = false;
    while (node = fzde(nuc)) {
        --p[node].de;
        path[++cnt] = node;
        for (int i = p[node].next; i; i = e[i].next) {
            --p[e[i].no].de;  // 把所有与该节点相连的点的度都减1
        }
    }
    if (cnt < N) {
        return 2;
    }
    else {
        return nuc ? 3 : 1;
    }
}

int main()
{
    char r[10];
    int x, y, flag;
    while (scanf("%d %d", &N, &M), N|M) {
        flag = 0;
        for (int i = 0; i < M; ++i) {
            scanf("%s", r);
            x = r[0]-'A'+1;  // NULL 要留出来进行结束判定
            y = r[2]-'A'+1;
            rec[i][0] = x, rec[i][1] = y;
        }
        for (int i = 0;  i < M && !flag; ++i) {
            init();
            for (int j = 0; j <= i; ++j) {
                insert(rec[j][0], rec[j][1]); // 每插入一条边进行一次判定,看是否可以得出结论
            }
            switch (topology()) {
                case 1: { // 1代表根据以上信息足以得到正确的拓扑关系
                    flag = 1;
                    printf("Sorted sequence determined after %d relations: ", i+1);
                    for (int k = 1; k <= cnt; ++k) {
                        printf("%c", path[k]+'A'-1);
                    }
                    puts(".");
                    break;
                }
                case 2: { // 2代表发生了冲突
                    flag = 1;
                    printf("Inconsistency found after %d relations.\n", i+1);
                    break;
                }
                case 3: {
                    
                    break;
                }  
            }
        }
        if (!flag) {
            puts("Sorted sequence cannot be determined.");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Lyush/p/2572450.html