前言
对于一个有向无环图(DAG),求拓扑排序最常见的方法:
① 从DAG图中选择入度为0的顶点,并输出。
② 从图中删除该入度为0的顶点及所有以它为起点的边。
③ 重复(1)和(2)直到当前图为空,或者图不存在入度为0的顶点。前者输出的序列就是拓扑排序;后者说明图中有环,不存在拓扑序列。
所以当需要判断某个图是否有环时,都应立刻想到求拓扑序列。
例题1
给出一个有向无环图,判断是否存在拓扑排序
输入
有多组测试用例。每组:
第一行:N(members),M(relationships);
接下来M行:(x,y)代表x—>y
当N=0,M=0时输入结束。
输出
若有拓扑排序,则输出“YES”,否则输出“NO”。
样例输入
3 2
0 1
1 2
2 2
0 1
1 0
0 0
样例输出
YES
NO
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=500;
vector<int> graph[MAXN];
int inDegree[MAXN];
bool TopologicalSort(int n)
{
queue<int> node;
for(int i=0;i<n;i++)
{
if(inDegree[i]==0)
node.push(i);
}
int number=0;//拓扑序列顶点个数
while(!node.empty())
{
int u=node.front();
node.pop();
number++;//拓扑序列顶点加1
for(int i=0;i<graph[u].size();i++)
{
int v=graph[u][i];
inDegree[v]--;//后续顶点入度减1
if(inDegree[v]==0)
node.push(v);
}
}
return n==number;//判断能否产生拓扑序列
}
int main()
{
int n,m;
while(cin>>n>>m)
{
if(n==0&&m==0)
break;
memset(graph,0,sizeof(graph));
memset(inDegree,0,sizeof(inDegree));
while(m--)
{
int from,to;
cin>>from>>to;
graph[from].push_back(to);
inDegree[to]++;
}
if(TopologicalSort(n))
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
例题2
确定多支队伍的比赛名次
输入
输入有若干组,每组:
第一行:N(队伍个数),M(队伍关系)
接下来M行:P1,P2(代表P1赢了P2,即P1—>P2)
输出
给出排名。
注意符合条件的排名可能不唯一,此时要求输出编号小的队伍在前
样例输入
4 3
1 2
2 3
4 3
样例输出
1 2 4 3
代码
本题已经明确该图是有向无环图,且采用优先队列,这样能保证编号小的顶点先输出。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=501;
vector<int> graph[MAXN];
int inDegree[MAXN];
vector<int> TopologicalSort(int n)
{
vector<int> topology;//拓扑序列
priority_queue<int,vector<int>,greater<int>> node;
for(int i=1;i<=n;i++)
{
if(inDegree[i]==0)
node.push(i);
}
while(!node.empty())
{
int u=node.top();
node.pop();
topology.push_back(u);//加入拓扑序列
for(int i=0;i<graph[u].size();i++)
{
int v=graph[u][i];
inDegree[v]--;//后续顶点入度减1
if(inDegree[v]==0)
node.push(v);
}
}
return topology;//判断能否产生拓扑序列
}
int main()
{
int n,m;
while(cin>>n>>m)
{
memset(graph,0,sizeof(graph));
memset(inDegree,0,sizeof(inDegree));
while(m--)
{
int from,to;
cin>>from>>to;
graph[from].push_back(to);
inDegree[to]++;
}
vector<int> answer=TopologicalSort(n);
for(int i=0;i<answer.size();i++){
cout<<answer[i]<<" ";
}
cout<<endl;
}
return 0;
}