题意描述:
给定字母表的前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, 0, sizeof(mp));
memset(indgr0, 0, sizeof(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, 0, sizeof(s));
if(Topological2() == 0)//存在回路,结束
{
gard = 3;
stp = i + 1;
break;
}
lstlen = 0;
for(j = 0; j < n; j++)
indgr1[j] = indgr0[j];
memset(s, 0, sizeof(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");
}
posted on 2012-08-16 19:19
小鼠标 阅读(1795)
评论(0) 编辑 收藏 引用 所属分类:
图论