問題與解答
問題描述
判斷有向圖中是否有環。
輸入格式
輸入數據第一行是一個正整數,表示n個有向圖,其余數據分成n組,每組第一個為一個整數,表示圖中的頂點個數n,頂點數不超過100,之后為有向圖的鄰接矩陣。
輸出格式
輸出結果為一行,如果有環,則輸出1,如果無環,則輸出0。按順序輸出這n個有向圖的判斷結果,前后結果的輸出不加空格。
樣例輸入
3
2
0 1
0 0
4
0 1 0 0
0 0 0 1
0 0 0 1
1 0 0 0
3
0 1 1
0 0 0
0 0 0
樣例輸出
010
//判斷有向圖中是否有環
//本質:拓撲排序
#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;
#define MaxN 100 //最大頂點數
int n; //頂點數
int G[MaxN][MaxN]; //鄰接矩陣保存圖
int InDegree[MaxN] = {0}; //保存頂點入度
void TopoSort(); //拓撲排序判斷有向環
int main(){
int num, i, j, flag;
scanf("%d", &num);
while(num--){ //多點輸入:執行num次
scanf("%d", &n);
fill(InDegree,InDegree+MaxN,0); //每次都要重置InDegree數組!
for(i = 0; i < n; i++){ //輸入圖的鄰接矩陣
for(j = 0; j < n; j++){
scanf("%d", &flag);
G[i][j] = flag;
if(flag != 0)
InDegree[j]++;
}
}
TopoSort(); //拓撲排序
}
}
void TopoSort(){
queue<int> q;
int u,v;
int node = 0;
for(u = 0; u < n; u++){ //將入度為0的頂點入隊
if(InDegree[u] == 0){
q.push(u);
}
}
while(!q.empty()){ //若隊列非空
u = q.front();
q.pop(); //u出隊
for(v = 0; v < n; v ++){ //掃描u的鄰接點
if(G[u][v] != 0){
InDegree[v]--; //鄰接點入度-1
if(InDegree[v] == 0) //若入度變為0,入隊
q.push(v);
}
}
node++; //已完成拓撲排序的頂點數目+1
}
if(node == n) printf("0"); //拓撲排序成功:無有向環
else printf("1"); //拓撲排序失敗:存在有向環
}
題后反思
- 判斷有向圖中是否有環: 拓撲排序
- 拓撲排序易錯點:兩層判斷是嵌套關系,否則會進入死循環!!!
if(G[u][v] != 0){ InDegree[v]--; //鄰接點入度-1 if(InDegree[v] == 0) //若入度變為0,入隊 q.push(v); }
- 寫多點測試題時注意全局變量的初始化【
fill(InDegree,InDegree+MaxN,0); //每次都要重置InDegree數組!
】否則樣例輸出011