• POJ-1094 拓扑排序


    POJ 1094

    题意:从'A'到'A'+n的n个字母,给出m个大小关系,求是否有特定的拓扑排序。

    总结:题目有点坑人。  1、不会有超出'A'+n范围的字母。  2、如果在输入第k个字母时,已经可以判断出有特定的排序或者判断出矛盾(即有环),就不用管后面的了。  3、判断是否有特定的排序,故有多种可能的应算作无序;而且如果即是无序又是矛盾的,应算作矛盾。

    // POJ-1094 
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<bitset>
    #include<vector>
    #include<set>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define F(i,a,b)  for (int i=a;i<b;i++)
    #define FF(i,a,b) for (int i=a;i<=b;i++)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    typedef long long ll;
    const int N = 30;
    
    int n, m, c;
    int G[N][N], indegree[N], List[N];
    
    int Toposort(int e)
    {
        int in[N], Q[N], top=0, flag=1;
        mes(List, 0);
        c=0;
        FF(i,1,n) {
            in[i]=indegree[i];
            if(in[i]==0) {
                Q[top++]=i, List[c++]=i, in[i]=-1;
            }
        }
        if(top>1) flag=0;
        while(top!=0) {
            int u=Q[--top];
            FF(i,1,n) if(G[u][i]) {
                in[i]--, e--;
                if(in[i]==0) {
                    Q[top++]=i, List[c++]=i, in[i]=-1;
                }
                if(top>1) flag=0;
            }
        }
        if(e!=0) return -1;
        return flag;
    }
    int main()
    {
        while(~scanf("%d%d", &n, &m) &&n&&m) {
            mes(G, 0);  mes(indegree, 0);
            int flag=0, ans=0;
            FF(i,1,m) {
                char str[10];
                scanf("%*c%s", str);
                if(flag==1) continue;
                int a=str[0]-'A'+1, b=str[2]-'A'+1;
                G[a][b]=1, indegree[b]++;
                int topo=Toposort(i);
                if(topo!=0) ans=i, flag=1;
                if(topo==1) {
                    printf("Sorted sequence determined after %d relations: ", ans);
                    F(i,0,c) printf("%c", 'A'+List[i]-1);
                    puts(".");
                }
                else if(topo==-1) {
                    printf("Inconsistency found after %d relations.
    ", ans);
                }
            }
            if(flag==0)  printf("Sorted sequence cannot be determined.
    ");
        }
    
        return 0;
    }
    View Code

    下面是大牛博客对拓扑排序Kahn算法的总结:

    不难看出该算法的实现十分直观,关键在于需要维护一个入度为0的顶点的集合:

    每次从该集合中取出(没有特殊的取出规则,随机取出也行,使用队列/栈也行,下同)一个顶点,将该顶点放入保存结果的List中。

    紧接着循环遍历由该顶点引出的所有边,从图中移除这条边,同时获取该边的另外一个顶点,如果该顶点的入度在减去本条边之后为0,那么也将这个顶点放到入度为0的集合中。然后继续从集合中取出一个顶点…………

    当集合为空之后,检查图中是否还存在任何边,如果存在的话,说明图中至少存在一条环路。不存在的话则返回结果List,此List中的顺序就是对图进行拓扑排序的结果。

  • 相关阅读:
    NSString
    xib和storyboard的使用方法
    drawRect画线和使用CGContext
    CGAffineTransform动画
    【概念】静态成员
    【c#】Application.Exit和Close有什么不同
    【c#】const和readonly关键字
    【概念】设计模式
    【概念】常见数据结构与算法
    【概念】索引器
  • 原文地址:https://www.cnblogs.com/sbfhy/p/6340531.html
Copyright © 2020-2023  润新知