poj1270 拓扑排序 (好久没写过这么详细的博客了^o^)

Following Orders
Time Limit:1000MS Memory Limit:10000K
Total Submissions:2504 Accepted:940

Description

Order is an important concept in mathematics and in computer science. For example, Zorn's Lemma states: ``a partially ordered set in which every chain has an upper bound contains a maximal element.'' Order is also important in reasoning about the fix-point semantics of programs.


This problem involves neither Zorn's Lemma nor fix-point semantics, but does involve order.
Given a list of variable constraints of the form x < y, you are to write a program that prints all orderings of the variables that are consistent with the constraints.


For example, given the constraints x < y and x < z there are two orderings of the variables x, y, and z that are consistent with these constraints: x y z and x z y.

Input

The input consists of a sequence of constraint specifications. A specification consists of two lines: a list of variables on one line followed by a list of contraints on the next line. A constraint is given by a pair of variables, where x y indicates that x < y.


All variables are single character, lower-case letters. There will be at least two variables, and no more than 20 variables in a specification. There will be at least one constraint, and no more than 50 constraints in a specification. There will be at least one, and no more than 300 orderings consistent with the contraints in a specification.


Input is terminated by end-of-file.

Output

For each constraint specification, all orderings consistent with the constraints should be printed. Orderings are printed in lexicographical (alphabetical) order, one per line.


Output for different constraint specifications is separated by a blank line.

Sample Input

a b f g
a b b f
v w x y z
v y x v z v w v

Sample Output

abfg
abgf
agbf
gabf

wxzvy
wzxvy
xwzvy
xzwvy
zwxvy
zxwvy


主要是 这次月赛 一个 背包问题 没AC!!! 下定决心好好看一下DP。 遗憾不想要第二次。 看一个DP相关的文档,中间 有提到 拓扑 排序。 所以,找了道题。 终于是对 topo 有点 理解了。

拓扑排序的资料:拓扑算法的演示动画

百度百科关于拓扑的概念: 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则u在线性序列中出现在v之前。

不过资料这东西 , 刚开始看 , 还是 觉得很模糊。 重要的是自己 慢慢想清楚!

我现在对 拓扑的理解: 拓扑排序就是 将一个 有向无环图 的所有点 排成一个 序列 ,使这个序列 越往右 越小。

例如 此题中 如果给 a , b ,f, g 四个点 , 给一组 方向关系 a>b , b > f . 那么 满足 的 拓扑序列 就有

abfg
abgf
agbf
gabf

四种。 大概就是这么个 意思。

看看这道具体的题。 输入的时候有点麻烦, 先构一个 DAG 图 (有向无环图,具体可以谷歌查查) ,然后 记录每个 点的入度, (主要就是理解 入度, 入度这东西我理解 就是 直接 通向这个点的路径 数, 如第一组 数据 , b,f 的入度就是1 , a,g 的入度就是0) 然后 从 入度为0 的点开始 DFS 深搜。 每次 取出 一个 点 ,就把 这个点 直接 限制的点 的入度 减一。 我自己更简单的理解就是,如 前文 的动画 演示 提供的一样, 每次 把没有 “上司”的 点取出来, “上司 ” 就是有多少直接管着这点的点。 然后 去掉 这个点后, 它的 下属 的上司数 就可以 减一了 ,重复 取 没有上司管的点 , 知道 取出 整个 topo 数列。


此题 我把所有 字母对应 为数字,。具体思路代码很详细。

此题的代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
	return *(int *)a - *(int *)b;
}
void dfs(int z,int count);
int a[25],dir[30][30],n,topo[25],vir[30],du[30]; //dir方向关系。du记录 度数。 vir标记是否访问。 a 数列 记录所有点。
int main()
{
//	freopen("in.txt","r",stdin);
	char ch[100];
	int len,i;
	while(gets(ch)!=NULL)
	{
		 //初始化
		memset(dir,0,sizeof(dir));
		memset(vir,0,sizeof(vir));
		memset(du,0,sizeof(du));

		len=strlen(ch);
		n=0;
		//记录点
		for(i=0;i<len;i++)
			if(ch[i]<='z' && ch[i]>= 'a')
				a[n++]= ch[i]-'a';
		qsort(a,n,sizeof(int),cmp);
		gets(ch);
		len=strlen(ch);
		int first=1,st,ed;
		for(i=0;i<len;i++)
		{
			if(first && ch[i]<='z' && ch[i] >='a')
			{
				first=0;
				st=ch[i]-'a';
				continue;
			}
			if(!first &&  ch[i]<='z' && ch[i] >='a')
			{
				first=1;
				ed=ch[i]-'a';
				dir[st][ed]=1;      //记录方向关系
				du[ed]++;           //记录度数
				continue;
			}
		}
		for(i=0;i<n;i++) if(!du[a[i]]) dfs(a[i],0);	  //从度数为0的点开始搜索
		putchar('\n');
	}
	return 0;
}

void dfs(int z,int count)
{
	int i;
	topo[count]=z;
	if(count==n-1)     //所有点取完了,满足 ,输出。
	{
		for(i=0;i<n;i++)
			printf("%c",topo[i]+'a');
		printf("\n");
		return ;
	}
	vir[z]=1;  //标记 为 已访问。
	for(i=0;i<n;i++)
	{
		if(!vir[a[i]] && dir[z][a[i]] )  
				du[a[i]] --;           //  把“下属”的度数减一
	}	
	for(i=0;i<n;i++)
		if(!du[a[i]] && !vir[a[i]] )    //度数为0的继续取。
	     	dfs(a[i],count+1);


	//下面几行很重要。 图的状态要复原!。
	for(i=0;i<n;i++)
	{
		if(!vir[a[i]] && dir[z][a[i]] )
				du[a[i]] ++;
	}
	vir[z]=0;
}

PS: 很久没写过这么详细的 博客了 。。。。。 以前觉得写详细点 有利于 自己更好的 理解。但总写 又 影响 效率。 以后 觉得 很有价值的 就写详细点吧

O(∩_∩)O哈哈~。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值