拓扑排序 模板

    了解拓扑排序之前,先要清楚一个概念:DAG(Directed Acyclic Graph)——有向无环图,即不包含有向环的有向图。
    在实际生活中常常会遇到这样的问题:在着手处理工作B之前先要处理完工作A和工作X,如何排列工作的顺序才能符合所有的条件?假若把每一种工作看作一个节点,工作顺序看作一条边,就可以得到一个有向无环图。将该图的节点进行排序,使得每一条有向边的起点都在终点之前,这种排序方式就是拓扑排序。 若图中存在有向环,则不可进行拓扑排序。
    拓扑排序的主要步骤:
    1.将入度为0的点输出
    2.将该点连接的所有边删除
    3.重复1,2两步直到所有点都输出

以下为模板代码: 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn=100;//最大顶点数 
int n,m;//n为顶点数,m为约束条件数量
int tol;//加边时统计边数
int indeg[maxn];//存储每个点的入度,注意每个样例都要初始化为0 
struct node
{
	int u,v;//u为起点,v为终点 
}edge[maxn*maxn];
void addedge(int u,int v)
{
	edge[tol].u=u;
	edge[tol].v=v;
	indeg[v]++;//统计入度 
}
int topo()
{
	queue <int> q;
	int cnt=0;//统计已排序的点的个数
	for(int i=0;i<n;i++)//注意编号,此处编号从0开始 
	{
		if(indeg[i]==0)//入度为0的点入列 
		q.push(i);
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		cnt++;
		for(int i=0;i<tol;i++)
		{
			if(edge[i].u==now)
			{
				indeg[edge[i].v]--;//翻边
				if(indeg[edge[i].v]==0)//如果入度为0,入队
				q.push(edge[i].v); 
			}
		}
	}
	if(cnt==n)//拓扑序存在 
	return 1;
	else
	return 0; 
} 

当然,也可用二维数组直接存图。然而,当数据很大的时候,以上代码有可能超时(二维数组存储会爆内存),所以利用不定长数组vector进行了一点优化。

下面放代码: 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=100000;//最大顶点数 
vector <int> pic[maxn];
int indeg[maxn];//储存入度
int main()
{
	int n,m;
	int begin,end;
	while(~scanf("%d%d",&n,&m)&&(n+m))
	{
		int cnt=0;//计数
		for(int i=0;i<=n;i++)//清空 
			pic[i].clear();
		memset(indeg,0,sizeof(indeg));//初始化
		while(m--)
		{
			scanf("%d%d",&begin,&end);
			indeg[end]++;//统计入度 
			pic[begin].push_back(end);//加边 
		}
		queue <int> q;
		for(int i=0;i<n;i++)
		{
			if(indeg[i]==0)//入度为0的点入队 
			q.push(i);
		}
		while(!q.empty())
		{
			int now=q.front();
			q.pop();
			cnt++;
			for(int i=0;i<pic[now].size();i++)
			{
				indeg[pic[now][i]]--;
				if(!indeg[pic[now][i]])
				q.push(pic[now][i]);
			}
		}
		if(cnt==n)
		printf("YES\n");
		else
		printf("NO\n");
	}	
	return 0;
} 

参考书籍:紫书,挑战程序设计竞赛2
练习题: HDU 3342HDU 1285, HDU 2094

猜你喜欢

转载自blog.csdn.net/qq_41279172/article/details/80753112
今日推荐