拓扑排序思想:
Kahn模板:每次取出入度为0的顶点删掉,并删掉和该点有关的边,需要维护一个入度为0的队列或者栈
//Kahn算法,关键在于需要维护一个入度为0的顶点的集合
int n,m;
int inDeg[N]; //i点的入度
vector<int>vec[N]; //i点的邻接表,即i与哪些点相连
int ans[N]; //排序结果数组
int topSort() //返回值代表是否有环,排序结果在ans数组
{
int cnt=0;
queue<int>q; //如果需要相同优先级的顶点,序号小的先输出,则可建立优先队列,即
//priority_queue<int,vector<int>,greater<int> >q;
while(!q.empty())
q.pop();
for(int i=1;i<=n;i++)
if(inDeg[i]==0)
q.push(i);
while(!q.empty())
{
int now = q.front();
q.pop();
ans[++cnt]=now; //个数+1并存数组
int len = vec[now].size();
for(int i=0;i<len;i++)
{
inDeg[vec[now][i]]--;
if(inDeg[vec[now][i]]==0)
q.push(vec[now][i]);
}
}
return (cnt==n)?1:0; //是否等于n,等于n代表无环
}
void init() //输入数据,n个点,m条边
{
int x,y;
cin>>n>>m;
for(int i=1;i<=n;i++)
vec[i].clear();
memset(inDeg,0,sizeof(inDeg));
for(int i=1;i<=m;i++)
{
cin>>x>>y;
inDeg[y]++;
vec[x].push_back(y);
}
}
DFS实现模板:
//dfs实现,从出度的角度来构造,递归到最后返回
int n,m;
vector<int>vec[N]; //i点的邻接表,即i与哪些点相连
int ans[N],cnt; //排序结果数组,cnt记录个数
int parent[N]; //记录其前置节点
//int d[N], Time, f[N]; //可以不要,时间time初始化为0,d[]记录第一次被发现时,f[]记录结束检查时
int vis[N]; //标记数组vis[i]=0表示还未访问过点i,c[i]=1表示已经访问过点i,并且还递归访问过它的所有子孙,c[i]=-1表示正在访问中,尚未返回
bool dfs(int s) //深度优先搜索(邻接表实现),记录时间戳,寻找最短路径
{
vis[s]=-1; //正在访问
//Time++;d[s]=Time;
int len = vec[s].size();
for(int i=0;i<len;i++)
{
int tmp=vec[s][i];
if(vis[tmp]<0) //如果子孙比父亲先访问,说明存在有向环,失败退出
return false;
else if(!vis[tmp]&&!dfs(tmp)) //如果子孙未被访问,访问子孙返回假,说明也是失败
return false;
parent[tmp]=s;
}
vis[s]=1;
//Time++;f[s]=Time;
ans[cnt++]=s; //结果是逆序的,递归的原因
return true;
}
bool topSort() //返回值代表是否有环,排序结果在ans数组
{
cnt=0;
for(int i=1;i<=n;i++)
{
parent[i]=-1;
vis[i]=0;
}
//Time=0;
for(int i=1;i<=n;i++)
if(!vis[i])
if(dfs(i)==false)
return false;
return true;
}
void init() //输入数据,n个点,m条边
{
int x,y;
for(int i=1;i<=n;i++)
vec[i].clear();
for(int i=1;i<=m;i++)
{
cin>>x>>y;
vec[x].push_back(y);
}
}