JZOJ #332 字典序最小的拓扑序

来源:JZOJ #332

题目描述

给定一个有 N N N 个节点的有向无环图(编号为 0 ∼ N − 1 0\sim N-1 0N1),求其拓扑排序的最小字典序。

解题思路

  • 仔细琢磨以后,会发现这道题是一道裸的拓扑排序。
  • 需要用到一种工具:堆,这样能保证一遍求完一定是字典序最小的拓扑序。当然了,使用 c + + c++ c++ 党福利: S T L ! ! ! STL!!! STL
  • 开一个优先队列(堆),不过默认是大根堆,我们手动把它改成小根堆,如下:
priority_queue<int,vector<int>,greater<int> >q;

代码君

#include 
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
const int maxn=100000+10,maxm=1000000+10;
struct node
{
	int y,next;
}e[maxm];
int n,m,tot=0,cnt=0;
int linkk[maxm],in[maxn],ans[maxn];
void insert(int x,int y)  //邻接表插入
{
	e[++tot].y=y;
	e[tot].next=linkk[x]; linkk[x]=tot;
}
void topsort()
{
	int head=1,tail=0;
	for (int i=0;i<n;i++)
	 if (in[i]==0) q.push(i);  //入度为0的先进队
	while (!q.empty())  //如果队列不为空
	{
		int x=q.top(); q.pop();  //取出队头,出队
		ans[++cnt]=x;
		for (int i=linkk[x];i;i=e[i].next)  //邻接表查询
		{
			int y=e[i].y;
			if (--in[y]==0)  //入度变为0
			{
				q.push(y);  //进队
			}
		}
	}
}
int main()
{
	freopen("topsort.in","r",stdin);
	freopen("topsort.out","w",stdout);
	memset(in,0,sizeof(in));
	scanf("%d %d",&n,&m);
	for (int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d %d",&x,&y);
		insert(x,y);  //插入
		in[y]++;  //入度+1
	}
	topsort();  //拓扑排序
	for(int i=1;i<=n;i++) printf("%d ",ans[i]);  //打印
	return 0;
}

你可能感兴趣的:(#,图论-拓扑排序,图论)