zoj1060,poj1094--拓扑排序

zoj1060,poj1094--拓扑排序
题意描述:
给定字母表的前n个大些字母,以及这些字母间两两之间的大小关系(这样的关系给定m组),问由这m组关系能否确定n个字母的整体顺序,如果能输出按续排列的字母。
显然,本题就是拓扑排序,不过题目的要求使得我们要处理一些细节。
下面我先说以下拓扑排序:
严蔚敏《数据结构》上的定义是: 由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序
直观的说偏序指集合中仅有部分成员之间可比较,而全序指集合中全体成员之间均可比较。
举个例子,一个大的工程通常有许多小的工程组成,这些小工程之间通常存在某些先后顺序;当然有些小工程之间不存在先后关系,它们是可以并行的。如果两个小工程直接或间接的相互依赖,就是两个小工程互为对方的先行条件,整个工程将无法进行下去。用一个个顶点分别表示这些小工程,用有向的边表示小工程之间的依赖关系,我们可以得到一个有向图。
拓扑排序可以帮助我们确定这些小工程开始的顺序,并且能够判定小工程之间是否存在相互依赖(图中是否有回路)。
拓扑排序的具体做法是:
1.在有向图中选择一个没有前驱(入度为0)的顶点,输出
2.从图中删除该顶点和所有以它为尾的弧,并更新相关点的入度
3.重复1,2步,直到所有顶点都被输出,或者发现图中存在回路。
如果结合上面所举的工程的例子,没有依赖(先后)关系的工程是可以并行的,但是就本题(zoj1060)而言,它要求每两个点之间的关系都是确定的,是不允许出现并行的,所以,当某一时刻,我们发现入度为0的点不止1个时,排序就失败了。
本题的输出分为三种情况,并且要求输出所用的条件个数,因此每增加一个条件就要做一次拓扑排序。
以下是本题代码,第一次写,有点乱,将就一下把~~
测试数据: http://poj.org/showmessage?message_id=133905


#include<stdio.h>
#include
<stdlib.h>
#include
<string.h>//zoj1060 poj1094
#define LEN 30
#define LEN_ORDER 10000
typedef 
struct
{
    
char a;
    
char c;
    
char b;
}Order;
int n, m;
Order od[LEN_ORDER];
int list[LEN];//存储最终的全序序列
int lstlen;

int indgr0[LEN];//各节点的入度
int indgr1[LEN];//是indgre0[]的副本
int mp[LEN][LEN];
int s[LEN];//记录该节点是否已排好序,== 1代表已排好
int zr;
int gard, stp;
int findZeroIndgr()// for Topological()
{
    
int i, j;
    
int a = -1;
    
int b = -1;
    
for(i = 0; i < n; i++)
    {
        
if(s[i] == 0 && indgr1[i] == 0)
        {
            
            a 
= i;
            
break;
        }
    }
    
for(i = i + 1; i < n; i++)
    {
        
if(s[i] == 0 && indgr1[i] == 0)
        {
            b 
= i;
            
break;
        }
    }
    
if(a == -1)
        
return -1;
    
else if(b != -1)
        
return 0;
    zr 
= a;
    
return 1;
}
int Topological()//这次拓扑排序用来确定全序关系
{
    
int i, j;
    
for(i = 0; i < n; i++)
    {
        
int t = findZeroIndgr();
        
if(t == -1 || t == 0)
            
break;
        
else 
        {
            list[lstlen
++= zr;
            s[zr] 
= 1;// in set
            for(j = 0; j < n; j++)//change in dgree
                if(mp[zr][j] == 1)
                    indgr1[j]
--;
        }
    }
    
if(lstlen == n)
        
return 1;
    
return 0;
}
int findZeroIndgr2()//for Topological2()
{
    
int i, j;
    
int a = -1;
    
for(i = 0; i < n; i++)
    {
        
if(s[i] == 0 && indgr1[i] == 0)
        {
            a 
= i;
            
break;
        }
    }
    
if(a == -1)
        
return 0;
    zr 
= a;
    
return 1;
}
int Topological2()//这次拓扑排序用来判是否存在回路
{
    
int i, j;
    
for(i = 0; i < n; i++)
    {
        
int t = findZeroIndgr2();
        
if(t == 0)
            
return 0;
        s[zr] 
= 1;
        
for(j = 0; j < n; j++)//change in dgree
            if(mp[zr][j] == 1)
                indgr1[j]
--;
    }
    
return 1;
}
int main()
{
    
int i, j, k;
    
int a, b;
    
//FILE *fp = fopen("out.txt", "w");
    FILE *fp = stdout;
    scanf(
"%d%d"&n, &m);
    
while(n + m != 0)
    {
        getchar();
        
for(i = 0; i < m; i++)
        {
            scanf(
"%c%c%c"&od[i].a, &od[i].c, &od[i].b);
            getchar();
        }
        gard 
= 2;
        memset(mp, 
0sizeof(mp));
        memset(indgr0, 
0sizeof(indgr0));
        
for(i = 0; i < m; i++)// make mp[][]
        {
            a 
= od[i].a - 'A';
            b 
= od[i].b - 'A';
            
if(od[i].c == '<' && mp[a][b] == 0)
            {
                mp[a][b] 
= 1;
                indgr0[b]
++;
            }
            
else if(od[i].c == '>' && mp[b][a] == 0)
            {
                mp[b][a] 
= 1;
                indgr0[a]
++;
            }
            
for(j = 0; j < n; j++)
                indgr1[j] 
= indgr0[j];
            memset(s, 
0sizeof(s));
            
if(Topological2() == 0)//存在回路,结束
            {
                gard 
= 3;
                stp 
= i + 1;
                
break;
            }
            
            lstlen 
= 0;
            
for(j = 0; j < n; j++)
                indgr1[j] 
= indgr0[j];
            memset(s, 
0sizeof(s));
            
if(Topological() == 1)//求出全序关系
            {
                gard 
= 1;
                stp 
= i + 1;
                
break;
            }
        }
        
        
if(gard == 1)
        {
            fprintf(fp, 
"Sorted sequence determined after %d relations: ", stp);
            
for(j = 0; j < lstlen; j++)
                fprintf(fp, 
"%c", list[j] + 'A');
            fprintf(fp, 
".\n");
        }
        
else if(gard == 2)
            fprintf(fp, 
"Sorted sequence cannot be determined.\n");
        
else
            fprintf(fp, 
"Inconsistency found after %d relations.\n", stp);
        scanf(
"%d%d"&n, &m);
    }
    fclose(fp);
    
//system("pause");
}

你可能感兴趣的:(zoj1060,poj1094--拓扑排序)