拓扑排序

拓扑排序

又叫topsort,对于一个oi选手来说。会用就行了(滑稽)

从一个点发出的边数叫做这个点的出度,而一个点被边指向的边的个数就叫做在这个点的入度。

将入读为0的点暂存,then将以这类点作为起点的边删除,相连的点入读-1,然后再将修改后入度为0的点暂存,重复此过程。(本人十分的蒟蒻,所以具体的拓扑排序过程只能大家去问度娘去了)

如果没有入度为0的点,但还有些点没有被遍历到,这就说明存在环。

这里为什么没有说明用什么数据结构储存入度为0的点呢?其实用什么都可以,先后顺序的什么都不重要(题目没有要求的话)

比如就是让你求一个拓扑序的话(配有spical judge),用什么都可以。

当然,有可能为了便于检查。题目会让你输出字典序最小的拓扑序,这时候就要用到堆。每次取出一个字典序最小的就行了。

哪拓扑排序有什么作用呢

举一个具体的例子。大家小学时都做过怎么安排泡茶才能让客人最快地喝上茶

有一系列的准备活动,而且有什么活动必须在什么活动开始之前完成。花费多少时间

我们将活动看成点,先后顺序看成有向边,花费的时间则看成有向边上的权值。

就将问题转化成了求出关键路径的长度

题目

最长路
裸的的拓扑排序,只不过起点和终点固定了。(预处理时可能会有坑)

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
vector<int>way[10600]; 
vector<int>price[1600];
int du[1600];
stack<int> s; 
int dis[1600]; 
int main()
{
	cin.sync_with_stdio(false);
	int n,m;
	cin>>n>>m;
	int p1,p2,v;
	for(int i=1;i<=n;i++)
		dis[n]=-0x7fffffff;
	dis[1]=0;
	for(int i=1;i<=m;i++)
	{
		cin>>p1>>p2>>v;
		if(p1>p2)
			swap(p1,p2); 
		way[p1].push_back(p2);
		price[p1].push_back(v);
		du[p2]++;
	}
	for(int i=2;i<=n;i++)
		if(!du[i])
			s.push(i);
	int pass;
	while(!s.empty())
	{
		pass=s.top();
		s.pop();
		int siz=way[pass].size();
		for(int i=0;i<siz;i++)
		{
			du[way[pass][i]]--;
			if(du[way[pass][i]]==0)
			{
				s.push(way[pass][i]);
			}
		}
	} 
	s.push(1); 
	while(!s.empty())
	{
		pass=s.top();
		s.pop();
		int siz=way[pass].size();
		for(int i=0;i<siz;i++)
		{
			dis[way[pass][i]]=max(dis[way[pass][i]],dis[pass]+price[pass][i]);
			du[way[pass][i]]--;
			if(du[way[pass][i]]==0)
			{
				s.push(way[pass][i]);
			}
		}
	} 
	if(dis[n]!=-0x7fffffff)
		cout<<dis[n];
	else
		cout<<"-1"; 
}
posted @ 2018-03-03 14:27  Lance1ot  阅读(221)  评论(0编辑  收藏  举报