无向图算法之CC算法

31 篇文章 2 订阅

CC算法

算法实现

#include "graph.h"
/*
    CC算法比union-find算法更慢.CC算法需要构建好一幅图
    但是union-find算法是一种动态算法,可以在添加边的时候去检查两个顶点是否连通

 */
class CC {  // 其实就是计算连通分量
 public:
  CC(Graph G) {
    marked_.resize(G.V(), false);
    id_.resize(G.V());
    for (int i = 0; i < G.V(); i++) {
      if (!marked_[i]) {
        dfs(G, i);
        count_++;
      }
    }
  }

  bool Connect(int w, int v) { return id_[w] == id_[v]; }

  void dfs(Graph& G, int v) {
    marked_[v] = true;
    id_[v] = count_;

    for (auto e : G.GetAdj(v)) {
      if (!marked_[e]) {
        dfs(G, e);
      }
    }
  }

 private:
  std::vector<bool> marked_;
  std::vector<int> id_;  // 记录的是该顶点属于哪一个连通分量
  int count_;
};

int main() {
  Graph graph(13);
  graph.ReadTxt("./map.txt");
  graph.Show();
  CC c(graph);
}

可以解决连通区域个数,以及判断顶点是否连通

Graph结构如下

#ifndef _GRAPH_H_
#define _GRAPH_H_

#include <fstream>
#include <iostream>
#include <list>
#include <string>
#include <vector>

class Graph {
 public:
  Graph(int v) : V_(v), E_(0) {
    // 分配空间
    adj.resize(V_);  // 代表有V个顶点
  }

  void AddEdge(int v, int w) {  // 添加边
    adj[v].push_back(w);
    // adj[w].push_back(v);
    E_++;
  }

  std::list<int> GetAdj(int v) { return adj[v]; }

  void ReadTxt(const std::string& file) {
    std::ifstream in;
    in.open(file, std::ios::in);
    if (!in.is_open()) {
      std::cout << "Open " << file << " Failed" << std::endl;
      return;
    }
    char ch;
    int V;
    int sum = 0;
    bool is_num = false;
    while (in.read(&ch, 1)) {
      if (ch == EOF) {
        break;
      } else if (ch == '\n') {
        AddEdge(V, sum);
        is_num = false;
        sum = 0;
      } else if (ch == ':') {
        V = sum;
        sum = 0;
        is_num = false;
      } else if (ch >= '0' && ch <= '9') {
        sum = sum * 10 + ch - '0';
        is_num = true;
      } else if (ch == ' ') {
        if (is_num) {
          AddEdge(V, sum);
          sum = 0;
          is_num = false;
        }
      }
    }
  }

  void Show() {
    std::cout << "V: " << V_ << " E: " << E_ << std::endl;
    int index = 0;
    for (auto& a : adj) {
      std::cout << "顶点: [" << index++ << "] ";
      for (auto v : a) {
        std::cout << v << " ";
      }
      std::cout << std::endl;
    }
  }

  inline int V() { return V_; }
  inline int E() { return E_; }

 private:
  int V_;                           // 顶点个数
  int E_;                           // 边的数目
  std::vector<std::list<int>> adj;  //邻接表
};

#endif

Graph代表的是无向图

map.txt内容如下

0: 6 2 1 5
1: 0
2: 0
3: 5 4
4: 5 6 3
5: 3 4 0
6: 0 4
7: 8
8: 7
9: 11 10 12
10: 9
11:9 12
12: 11 9
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值