有向图,
先进行拓补排序,若数组中个数等于n则无环 否则有环
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
vector<int>e[1005];
int out[1005];
void topsort( int n )
{
int i;
int a[1005];
priority_queue<int>q;
for( i = 1; i<=n; i++)
{
if( out[i] == 0 )
q.push( i );
}
int k = 0;
while( !q.empty())
{
int s = q.top();
a[k++] = s;
q.pop();
for( i =0; i<e[s].size(); i++)
{
out[e[s][i]]--;
if( out[e[s][i]] == 0)
q.push( e[s][i] );
}
}
if( n == k )
{
for( i =k-1; i>0 ;i--)
{
printf("%d ", a[i]);
}
printf("%d\n", a[0]);
}
else
printf("IMPOSABLE\n");
}
int main()
{
int n, m, i;
while(scanf("%d%d", &n, &m) != EOF )
{
for( i =1; i<=n; i++)
{
out[i] = 0;
e[i].clear();
}
int a,b;
for( i =0; i<m; i++)
{
scanf("%d%d", &a, &b );
e[b].push_back( a );
out[a]++;
}
topsort( n );
}
return 0;
}
无向图
无向图中当顶点的数量和边的数量很大的时候,使用dfs存在大量的递归,会导致栈溢出。使用下面的方法可以有效的避免。
判断无向图中是否存在回路(环)的算法描述
如果存在回路,则必存在一个子图,是一个环路。环路中所有顶点的度>=2。
算法:
第一步:删除所有度<=1的顶点及相关的边,并将另外与这些边相关的其它顶点的度减一。
第二步:将度数变为1的顶点排入队列,并从该队列中取出一个顶点重复步骤一。
如果最后还有未删除顶点,则存在环,否则没有环。
算法分析:
由于有m条边,n个顶点。如果m>=n,则根据图论知识可直接判断存在环路。
(证明:如果没有环路,则该图必然是k棵树 k>=1。根据树的性质,边的数目m = n-k。k>=1,所以:m<n)
如果m<n 则按照上面的算法每删除一个度为0的顶点操作一次(最多n次),或每删除一个度为1的顶点(同时删一条边)操作一次(最多m次)。这两种操作的总数不会超过m+n。由于m<n,所以算法复杂度为O(n)