先从一到HDoj的题目入手
HDOJ 1285 AC代码
这里只需要记录入度和顶点的联通性质就可以了。
三重循环算法:
1.第一层循环:代表每次排出一个点来
2.第二层循环:寻找入度为0的一个点
3 第三层循环:寻找入度为0的点相联通的点,它们的入度减1
O(n^3) 复杂度高的原因:用邻接矩阵,想找相邻顶点是O(N),如果是邻接表就是O(1)
<pre name="code" class="cpp">#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=520;
bool connect[maxn][maxn];
int in[maxn];
int N,M;
void topsort(){
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
if(in[j]==0){
in[j]=-1;
printf("%d",j);
if(i!=N) printf(" ");
for(int k=1;k<=N;k++){
if(connect[j][k]){
in[k]--;
}
}
break;
}
}
}
printf("\n");
}
int main(int argc, char const *argv[])
{
while(cin>>N>>M){
memset(connect,false,sizeof(connect));
memset(in,0,sizeof(in));
int a,b;
for(int i=0;i<M;i++){
scanf("%d %d",&a,&b);
if(!connect[a][b]){
connect[a][b]=true;
in[b]++;
}
}
topsort();
}
return 0;
}
一些小小的优化:
使用队列
1.检测入度为0的点,加入队列
2.while(队列非空)
弹出队首元素,检测与他相邻的点,入度减一,如果入度为0,加入队列。
3.当队列为空的时候,检测队列弹出元素是否是n个,否则说明不是DAG
拓扑排序的一些定义和算法
一个有向图能被拓扑排序的充要条件就是它是一个有向无环图(DAG:Directed Acyclic Graph)。
拓展到拓扑排序中,结果具有唯一性的条件也是其所有顶点之间都具有全序关系。如果没有这一层全序关系,那么拓扑排序的结果也就不是唯一的了。在后面会谈到,如果拓扑排序的结果唯一,那么该拓扑排序的结果同时也代表了一条哈密顿路径。
典型实现算法:
Kahn算法 :
关键在于需要维护一个入度为0的顶点的集合:
每次从该集合中取出(入度为0)的一个顶点,将该顶点放入保存结果的List中。