//拓扑排序裸题,题目要求按编号从小到大输出,要换一种思维去思考
//按照数据结构课本的算法,建立邻接表,用栈实现。初始化先将入度为0的顶点入栈,然后以栈顶顶点为准,先将栈顶顶点出栈输出它的信息,然后扫描它的邻接表,没找到一个弧头就将其入度减1,减1后判断该弧头是否入度为0,是的话就入栈。直到所有顶点都出栈那么就输出了一个拓扑序列。但是这样做不能保证编号从小到大输出
为了保证从小到大输出,要用“每次都从头来过”的思想,因为题目保证一定存在拓扑序列,所以对于n个点,一定输出n次,所有外循环是次数,找到了n次,输出n个点,然后每次找,都是按照编号从1找到n,所以内循环是对应顶点的编号,从1到n,从当找到一个顶点,还没有纳入拓扑序列并且入度为0,就输出这个顶点的信息,并且扫描它的邻接表,将所有的弧头的入度都减1,然后再从头找过
所以找了n次,从次都是从编号1到n地扫描所有顶点,这样就能保证拓扑序列的正确性,而且因为编号都是从小到大扫描的,那么保证了先输出了编号小的
//用数组来实现邻接表 #include#include #define MAXN 510#define MAXM 250100bool g[MAXN][MAXN],vis[MAXN]; //g对应边集数组,体重可能有重复,vis记录那些顶点已经纳入序列int u[MAXM],v[MAXM]; //保存弧u->vint first[MAXN]; //对应每个顶点的邻接表的第一条弧的编号int in[MAXN]; //对应每个顶点的入度int nextt[MAXM]; //对应一条弧的下一弧的编号int n,m;void input(){ int i,j,k; memset(first , -1, sizeof(first)); memset(in,0,sizeof(in)); memset(g,0,sizeof(g)); for(i=0; i