無向グラフが接続されているかどうかを確認します
- DFS、BFSは、すべての頂点にアクセスできるかどうかに関係なく、グラフを走査します。
- そして、セットを確認してください。
グラフにリングがあるかどうかを確認します
有向グラフ:有向グラフのリングは、特に同じ方向のリングを指します
[外部リンク画像の転送に失敗しました。ソースサイトにヒル防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-hsVSlpDr-1584972787667)(http://note.youdao.com/noteshare? id = d98bba32026574ec204adac734ccdaf7&sub = 4699EAF86DEF463A8BE50FC418E4108A)]
1。トポロジカルソート
//邻接表版
class Solution{
public:
bool topologicalSort(vector<vector<int> >& graph){
int V = graph.size();
int in_degree[V] = {
};
for(vector<int> v:graph){
for(int x:v) in_degree[x]++;
}
//topo
int num = 0; //拓扑排序成功的顶点个数
queue<int> q;
for(int i=0; i<V; i++){
if(in_degree[i]==0) q.push(i);
}
while(!q.empty()){
int v = q.front();
q.pop();
cout<<v<<' ';
num++;
for(int u:graph[v]){
in_degree[u]--;
if(in_degree[u]==0) q.push(u);
}
}
if(num==V) return true;
else return false;
}
};
2.有向グラフのタージャンアルゴリズム(基本的にDFS)
の強連結成分は、リングまたはポイントのいずれかです。タージャン
//邻接矩阵版
class Solution{
public:
int V, time; //顶点个数,时间戳
vector<int> dfn, low;
vector<bool> in_stack; //记录顶点是否在栈内
stack<int> s;
vector<vector<int> > tarjan(vector<vector<int> >& graph){
//init
V = graph.size();
dfn.resize(V, 0); //dfn[i]=0还可表示i还未访问到
low.resize(V, 0);
in_stack.resize(V, false);
time = 1;
vector<vector<int> > ans;
//tarjan
for(int i=0; i<V; i++){
if(dfn[i]==0) DFS(i, graph, ans);
}
return ans;
}
void DFS(int i, vector<vector<int> >& graph, vector<vector<int> >& ans){
s.push(i);
in_stack[i] = true;
dfn[i] = low[i] = time++;
for(int j; j<V; j++){
if(graph[i][j]){
if(dfn[j]==0){
DFS(j, graph, ans);
low[i] = min(low[i], low[j]);
}
else if(in_stack[j]) low[i] = min(low[i], dfn[j]);
}
}
if(dfn[i]==low[i]){
vector<int> temp;
int x;
do{
x = s.top();
s.pop();
temp.emplace_back(x);
}while(x!=i);
ans.emplace_back(temp);
}
return;
}
};
無向グラフ
1.Nアルゴリズム
//邻接矩阵版
class Solution{
public:
bool nAlgorithm(vector<vector<int> >& graph){
int V = graph.size();
int degree[V] = {
};
for(int i=0; i<V; i++){
for(int j=0; j<V; j++){
if(graph[i][j]!=0){
degree[i]++;
degree[j]++;
}
}
}
//把所有度<=1的顶点入队,只要入过队,就一定不在环里
queue<int> q;
int num = 0; //入过队的顶点数
for(int i=0; i<V; i++){
if(degree[i]<=1) q.push(i);
}
while(!q.empty()){
int v = q.front();
q.pop();
num++;
for(int j=0; j<V; j++){
if(graph[v][j]!=0){
degree[v]--;
degree[j]--;
if(degree[j]==1) q.push(j);
}
}
}
if(num<V) return true; //有环
else return false;
}
};
2.ユニオン検索セット
ユニオン検索セットは、一般にツリー構造を処理するために使用され、ツリーのエッジは有向エッジと見なすことができます。
グラフを処理する場合、圧縮できるのはパスのみであり、元のパスが失われるため、リングの存在のみを判断でき、リングを出力することはできません。
エッジに遭遇するたびに、結合が実行されます。リングがある場合、リングシールの端まで処理するとき、2つの頂点の父は同じです。
//邻接矩阵版
class Solution{
public:
vector<int> father; //father存原始路径
bool cyclic(vector<vector<int> >& graph){
int V = graph.size();
father.resize(V);
for(int i=0; i<V; i++) father[i] = i;
for(int i=0; i<V; i++){
for(int j=0; j<V; j++){
if(graph[i][j]!=0){
if(!union_set(i, j)) return true; //有环
}
}
}
return false;
}
int findFather(int a){
int t = a;
while(a!=father[a]) a = father[a];
while(t!=father[t]){
int u = father[t];
father[t] = a;
t = u;
}
return a;
}
bool union_set(int a, int b){
int fa=findFather(a), fb=findFather(b);
if(fa!=fb){
father[fa] = fb;
return true;
}
else return false; //出现环
}
};
3、DFS