poj1094Sorting It All Out 拓扑排序

  做拓扑排序的题目,首先要知道两条定理:

    1、最后得到的拓扑数组的元素个数如果小于n,则不存在拓扑序列。  (有圈)

    2、如果一次入队的入度为零的点数大于1,则拓扑序列不唯一。  (关系不确定)

  本题有一个默认的东西,如果到了第K(看K<m)步,能唯一确定一个序列,就不用管之后会不会产生矛盾。

  这题的思路还是比较清晰的。输入也只有X<Y(只有<符号,并且X,Y都只是大写字母),数据量比较小。不过边数没有限制,用链式前向星的话不太好,还是用邻接矩阵吧。每次用邻接矩阵要注意的是判断重边,做小生成树的时候是用初始化边为无穷大,然后每次取小的。但是这里没有边权,所以只要有边,赋值为1,就可以了。遇到重边的话,不能再加入度。

  只需要拓扑排序就可以解决这个问题了。我就犯了画蛇添足的错误,我居然用floyd去判圈。这主要是对拓扑排序理解不够的原因。当出现的字母的数字小于n时,没出现的字母的入度是零,所以不影响拓扑排序产生的数据元素的个数。只有有圈的情况才会使得数组元素个数小于n。

  还有,我犯了一个很二的错误。因为没输入一组数据就要做一次拓扑排序。我居然把统计入度的数组没有变化就用了。囧了。再声明一个数组,每次拓扑排序之前,把入度数组的数据复制过来就好了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int N = 30;
int ind[N],que[N], g[N][N],id[N];
int iq,flag, T;
void topo(int n)
{
    int i,k,j=0,x;
    T=0;
    for(i=1;i<=n;i++)
    {
        id[i]=ind[i];
        if(id[i]==0) que[j++]=i;
    }
    if(j>1) T=1;
    x=j;
    for(i=0;i<j;i++)
    {
        if(j-x>1) T=1;
        x=j;
        int u=que[i];
        for(k=1;k<=n;k++)
        {
            if(g[u][k]&&u!=k)
            {
                id[k]--;
                if(id[k]==0) que[j++]=k;
            }
        }
    }
    iq=j;
}
void init()
{
    flag=0;
    memset(ind,0,sizeof(ind));
    memset(g,0,sizeof(g));
}
int main()
{
    //freopen("test.txt","r",stdin);
    int n,m,i,j,k,t,a,b;
    char ch1,ch2,ch;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(!n) break;
        init();
        t=0;
        for(k=1;k<=m;k++)
        {
            do
                scanf("%c",&ch1);
            while (!isalpha(ch1)) ;
            scanf("<%c",&ch2);
            if(flag) continue;
            a=ch1-64,b=ch2-64;
            if(a>n||b>n||a==b) flag=1;
            if(flag) {printf("Inconsistency found after %d relations.\n",k);continue;}
            if(g[a][b]) continue;
            g[a][b]=1;
            ind[b]++;
            topo(n);
            if(iq<n){flag=1;printf("Inconsistency found after %d relations.\n",k);continue;}
            if(iq==n&&!T){
                flag=1;
                printf("Sorted sequence determined after %d relations: ",k);
                for(i=0;i<n;i++) printf("%c",que[i]+64);
                printf(".\n");
                continue;
            }
            if(k==m&&!flag) printf("Sorted sequence cannot be determined.\n");
        }
    }
    return 0;
}
时间: 2024-07-29 05:37:59

poj1094Sorting It All Out 拓扑排序的相关文章

poj1094Sorting It All Out——拓扑排序

题目:http://poj.org/problem?id=1094 看到此题,首先觉得这是一种层层递进的关系,所以可以想到用拓扑排序: 就像人工排序,每次需要找到一个最小的,再找到新的最小的--所以用有向边代表小的元素到大的元素的关系,每次的入度为0的点就是最小的: 出现错误也就是出现了环,可以看做是拓扑排序过程后还有没有被排到的点,也就是怎样入度都不为0: 因为要输出哪一步,所以就一步一步,每一步上建图.判断等等: 注意因为上一步不能影响下一步,所以排序中不能把真的入度减去. 代码如下: #i

POJ--1094--Sorting It All Out【拓扑排序】

链接:http://poj.org/problem?id=1094 题意&思路:直接拓扑排序.多解输出一串英文,有环输出一段英文,唯一解输出一段英文及排序结果. 细节:题目描述不是很清楚,如果不看discuss我肯定要WA出翔. discuss里总结了两点关键的: 1. 输入一条边时如果此时拓扑有解就输出这个解,即使后面的边成有向环也不管了,所以每次输入的时候都得进行拓扑排序. 2. 判断存在有向环应先于判断多解. 这道题主要是题目坑爹. #include<cstring> #incl

拓扑排序讲解

在这里我们要说的拓扑排序是有前提的 我们在这里说的拓扑排序是基于有向无环图的!!!. (⊙o⊙)…我所说的有向无环图都知道是什么东西吧.. 如果不知道,我们下面先来来说说什么是有向无环图. 所谓有向无环图,顾名思义是不存在环的有向图(至于有向图是什么不知道的在前面我们有一个图论讲解上都有). 点的入度:以这个点为结束点的边数. 点的出度:以这个点为出发点的边的条数. 拓扑序就是对于一个节点的一个排列,使得(u,v)属于E,那么u一定出现在v的前面.然而拓扑排序就是一个用来求拓扑序的东西. 对于左

CSU 1804: 有向无环图(拓扑排序)

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 题意:…… 思路:对于某条路径,在遍历到某个点的时候,之前遍历过的点都可以到达它,因此在这个时候对答案的贡献就是∑(a1 + a2 + a3 + ... + ai) * bv,其中a是之前遍历到的点,v是当前遍历的点. 这样想之后就很简单了.类似于前缀和,每次遍历到一个v点,就把a[u]加给a[v],然后像平时的拓扑排序做就行了. 1 #include <bits/stdc++.h>

7-9-有向图无环拓扑排序-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第7章  图 - 有向无环图拓扑排序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.SequenceStack.c.ALGraph.c    

hihoCoder 1175:拓扑排序二

题目链接: http://hihocoder.com/problemset/problem/1175 题目难度:一星级(简单题) 今天闲来无事,决定刷一道水题.结果发现这道水题居然把我卡了将近一个钟头. 最后终于调通了.总结起来,原因只有一个:不够仔细. 思路不用细说了,就是拓扑排序的简单应用.然而,一些不起眼的细节才是让你掉坑里的真正原因. 猜猜哪儿可能出bug? // A simple problem, but you can't be too careful with it. #inclu

hdu1285(拓扑排序)

这道题要求没有输赢关系的两个元素必须按照升序输出,有输赢关系的,赢得在输的前面,所以用队列或者栈来降低时间复杂度的优化过的拓扑排序会出错. 比如这组输入 5 3 1 2 2 3 4 5 至少我写的两种拓扑排序都wa了.但是不用队列或者栈来优化的话, 1.每次都从头至尾扫描一遍,找到一个没标记过的节点, 2.将它标记 3.然后删除从它出来的每条边. 重复这三个操作,加标记的次序,就是题目要的答案. 下面的代码中用到了队列,但只是用来保存答案而已.并没有用它优化的意思. #include <iost

uva 10305 Ordering Tasks(拓扑排序)

拓扑排序,不用判断是否有环,dfs挺简单的 代码: #include<stdio.h> #include<string.h> #include<stdlib.h> int map[105][105]; int visit[105]; int c[105]; int n,m,t; void dfs(int x) { visit[x] = 1; for(int i=1; i<=n; i++) { if(!visit[i]&&map[i][x]==1)

NOJ 2015年陕西省程序设计竞赛网络预赛(正式赛)(忙碌的选课系统-拓扑排序注意重边)

D - 忙碌的选课系统 Time Limit: 10000 ms        Memory Limit: 65536 KB Submit Description 每学期末,都是万众瞩目的选课时间,由于人数过多,某学校的服务器常常被无数的学生挤的爆掉,这是,教务系统大人说,你们选个课都这么慢,居然还怪我们.于是,每次教务系统都会在服务器快要瘫痪前关闭它.在无数学生的强烈抗议下,教务系统妥协了,再给每个人一次机会,但他让我们用最快的方式决定该选的课程,选上后就退出. 这让大一学渣狗犯了难,在新的选