拓扑排序的实现步骤
1. 在有向图中找出没有前驱的顶点输出,也就是入度为0的顶点;
2.从有向图中删除这个入度为0的顶点,并将与这个顶点相连的顶点的入度减1;
3.重复上述两步,直到循环了 n次(有n个顶点);
例题1: 求下面这个图的一个拓扑排序
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector> //利用队列来存储顶点和顶点的入度
using namespace std;
const int maxn = 1000;
int p[maxn][maxn]; //邻接矩阵,判断两个点是否连通
int in[maxn];
int n,m;
struct node{
int u,w;
node(int x,int y){
u = x,w = y;
}
friend bool operator<(const node &e1,const node &e2){ //定义sort根据顶顶点的入度排序
return e1.w < e2.w;
}
};
int main(){
cin>>n>>m;
memset(in,0,sizeof in);
memset(p,0,sizeof p);
vector<node>q;
for(int i = 0;i < m; i++){
int a,b; //输入一个从a到b的有向边
cin>>a>>b;
p[a][b] = 1;
in[b]++; //b的入度加1
}
for(int i = 1; i <= n ;i++)
q.push_back(node(i,in[i])); //将顶点和顶点的入度写入队列
sort(q.begin(),q.end()); //将队列根据 顶点的入度排序 入度小的在前面
for(int i = 0; i < n;i++){ //拓扑排序 循环n次
cout<<q[0].u<<endl;
int mod = q[i].u;
q.erase(q.begin()); //删除入度为0的顶点 (入度最小)
for(int j = 0; j < q.size() ;j++)
if(p[mod][q[j].u] && q[j].u!= mod)
q[j].w--; //与mod相邻的顶点的入度减1
sort(q.begin(),q.end()); //重新排序
}
return 0;
}
例二:
http://acm.hdu.edu.cn/showproblem.php?pid=1285
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 505;
const int inf = INT_MAX;
int p[maxn][maxn];
int in[maxn];
struct node{
int u,w;
node(int x,int y){
u = x,w = y;
}
bool friend operator<(const node &e1,const node &e2){
return e1.w < e2.w;
}
};
int n,m;
int main(){
cin>>n>>m;
vector<node>q;
memset(p,0,sizeof p);
memset(in,0,sizeof in);
for(int i = 1 ;i <= m; i++){
int a,b;
cin>>a>>b;
p[a][b] = 1;
in[b]++;
}
for(int i = 1 ; i <= n ;i++)
q.push_back(node(i,in[i]));
for(int i = 1; i <= n ;i++){
int minx = inf;
int loc ;
int len;
for(int j = 0; j < q.size();j++){
if(q[j].w < minx){
loc = q[j].u;
minx = q[j].w;
len = j;
}
else if(q[j].w == minx){
if(q[j].u < loc)
{
loc = q[j].u;
len = j;
}
}
}
q.erase(q.begin() + len);
printf("%d%c",loc,i == n ? '\n':' ');
for(int j = 0;j < q.size();j++){
if(p[loc][q[j].u] && loc!= j)
q[j].w--;
}
}
}