不是所有图都可以进行拓扑排序
只有有向无环图才可以进行拓扑排序
有向无环图也称为拓扑图
一个有向无环图,一定至少存在一个入度为0的点。
拓扑排序不是唯一的。
拓扑排序思路:
class Solution {
private:
int r[2010];//入度表
bool st[2010]; //判重数组
int h[2010],e[4010],ne[4010],idx=0; //数组模拟邻接表
//这里h的大小和图中的点数是一个规模的,而e和ne的大小和图中的边数是一个规模的,所以不能太小
public:
void add(int a,int b) //在邻接表上加一条边
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
memset(r,0,sizeof(r));
memset(st,0,sizeof(st));
memset(h,-1,sizeof(h)); //初始化为全-1
for(int i=0;i<prerequisites.size();i++)
{ //遍历一遍关系,建立邻接表和入读表
add(prerequisites[i][1],prerequisites[i][0]);
r[prerequisites[i][0]]++;
}
vector<int> k;
int q[2010],tt=-1,hh=0; //数组模拟队列
//先遍历一遍入度表,把所有入度为0的点都入队,他们之间的先后顺序无所谓
for(int i=0;i<numCourses;i++)
if(r[i]==0)
{
q[++tt]=i;
st[i]=true;
k.push_back(i);
}
while(hh<=tt)
{
int t=q[hh];
hh++;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(!st[j]) //没被访问过
{
r[j]--; //把当前点删去,相应的入度减一
if(r[j]==0) //如果产生了新的入度为0的点,入队
{
q[++tt]=j;
st[j]=true;
k.push_back(j);
}
}
}
}
if(tt==(numCourses-1)) 因为数组模拟队列,队尾tt的位置可以反映从头到尾一共有多少元素进过队
return k;
else
{
k.clear();
return k;
}
}
};