连通图_连通分量FloodFill

原创 2016年06月01日 19:12:43

首先,我们来介绍一个概念:子图(subgraph)。若一个图的顶点集和边集分别是另一图的顶点集的子集和边集的子集,则称该图为另一图的子图。

换句话说,从一个图里选出一部分顶点和边,只要确保选择的边对应的两个顶点也都被选择,那么所有选出的顶点和边组成的图就是原图的子图。

就像在一个社交网络中,同班同学的帐号之间的关系就组成了整个社交网络的一个子图。

接下来,我们介绍一个概念:连通。在无向图中,如果有从顶点 vv 到顶点 ww 的路径存在,则称 vv 和 ww 是连通的。若图 GG 中任意两个顶点都是连通的,则称图 GG 为连通图,否则成为非连通图。

若图 G 的子图Gs是连通的,我们就称子图 G​s是图 G 的连通子图。如果对于图 G 的一个连通子图G​s,不存在图 G 的其他连通子图 G​max满足:Gs是 Gmax的子图。则子图 G​s 是图 G的极大连通子图,也就是图 G 的连通分量。

如何求解无向图的连通分量呢?这要用到我们本章介绍的第一个图论算法:FloodFill 算法。

FloodFill 算法通常译作“洪水灌溉法”,算法通过给图中的顶点染色,最终使得同一个连通分量的顶点颜色相同,不同连通分量的顶点颜色不同。算法的描述如下:

  1. 找到一个没有染色的顶点,将其染为新的颜色 Color_{new}Color
    ​new
    ​​ ,如果没有则算法结束。

  2. 初始化一个空的队列,并将第一步的顶点插入队列。

  3. 不断获得队首元素的值并弹出,将和队首元素相邻的未染色顶点染为 Color_{new}Color
    ​new
    ​​ ,并将其加入队列。

  4. 重复执行第一步,直到所有顶点都被染色,算法结束。

FloodFill 的时间复杂度是 O(V+E)O(V+E),其中广度优先遍历的部分可以替换成深度优先遍历,复杂度是一样的。通常考虑到递归调用的时间开销,往往广度优先遍历的效率要更高一些。

#include <iostream>
#include <vector>
#include <cstring>
#include <queue>

using namespace std;

class Graph {
private:
    int n;
    int * color;
    vector<int> * edges;


public:
    Graph(int input_n) {
        n = input_n;
        edges = new vector<int>[n];
        color = new int[n];
        memset(color, 0, n * sizeof(int));
    }

    ~Graph() {
        delete[] edges;
        delete[] color;
    }

    void insert(int x, int y) {
        edges[x].push_back(y);
        edges[y].push_back(x);
    }

    void floodfill() {
         int color_cnt=0;
        for(int i=0;i<n;++i){
            if(color[i]==0){
                //不同联通分量内的结点标记不同颜色
                color_cnt++;
                color[i]=color_cnt;
                queue<int> q;
                //未标记结点入队
                q.push(i);
                while(!q.empty()){
                    int vertex= q.front();
                    //依次标记与之有边的结点,并将标记后的节点入队
                    for(int j:edges[vertex]){
                        if(color[j]==0){
                            color[j]=color_cnt;
                            q.push(j);
                        }
                    }
                    q.pop();
                }
            }
        }
        for(int i=0;i<n;++i){
            cout<<i<<" "<<color[i]<<endl;   
        }
    }
};

int main() {
    int n, m, k;
    cin >> n >> m;
    Graph g(n);
    for (int i = 0; i < m; ++i) {
        int x, y;
        cin >> x >> y;
        g.insert(x, y);
    }
    g.floodfill();

    return 0;
}
版权声明:ShirleyPaul原创,未经博主允许不得转载

相关文章推荐

十二、图的算法入门--(1)连通分量和FloodFill算法

摘自计蒜客:http://www.jisuanke.com/course/35/7547 一、连通分量和FloodFill算法 首先,我们来介绍一个概念:子图(subgraph)。若一个图的顶点集和边...

连通图和连通分量

连通图和连通分量   1.顶点间的连通性      在无向图G中,若从顶点vi到顶点vj有路径(当然从vj到vi也一定有路径),则称vi和vj是连通的。 2.连通图      若V(G)中任意两个...

[kuangbin带你飞]专题九 连通图 A - Network of Schools (强连通分量)(模板)

强连通分量的模板题,设 a 为出度为1的点个数,设 b 为入度为1 的点个数,要求的是a和max(a,b)。 把处于一个强连通分量的点染色,再求出度和入度即可。 这里的模板是两个dfs,一个原图,...

POJ 3177(带重边的连通图的双连通分量)

题目大意:求带重边的连通图至少加几条边变成双连通图 POJ 3352 +重边 用邻接矩阵的表示无压力 Program P3177; const maxn=1000; m...

【ZSTU4213 2015年12月浙理工校赛 D】【双连通分量tarjan算法】One-Way Roads 无向连通图确定边的方向使得全图任意两点间可达

4213: One-Way Roads Time Limit: 1 Sec  Memory Limit: 128 MB  Special Judge Submit: 133  Solved: 45...

连通图的割点、割边(桥)、块、缩点,有向图的强连通分量

转载自:http://hi.baidu.com/scameeling/blog/item/60f25a8dc50347e3f01f36f0.html 一、基本概念 无向图 割点:删掉它之后(删掉...

连通图的割点、割边 连通图的割点、割边(桥)、块、缩点,有向图的强连通分量

连通图的割点、割边 连通图的割点、割边(桥)、块、缩点,有向图的强连通分量 一、基本概念 无向图 割点:删掉它之后(删掉所有跟它相连的边),图必然会分裂成两个或两个以上的 子图。 块:没有割...
  • CSDN515
  • CSDN515
  • 2012年08月23日 10:23
  • 3767

有向图的强连通分量

  • 2015年07月17日 11:54
  • 651KB
  • 下载

无向连通图求割点(tarjan算法去掉改割点剩下的联通分量数目)

poj2117 Electricity Time Limit: 5000MS   Memory Limit: 65536K Total Submissions...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:连通图_连通分量FloodFill
举报原因:
原因补充:

(最多只允许输入30个字)