igraph 参考手册

用于使用 igraph C 库

搜索手册

第 23. 章 顶点分隔符

1. igraph_is_separator — 移除这组顶点是否会断开图?

igraph_error_t igraph_is_separator(const igraph_t *graph,
                                   const igraph_vs_t candidate,
                                   igraph_bool_t *res);

顶点集 S 是一个分隔符,如果在图中存在顶点 uv,使得 uv 之间的所有路径都经过 S 中的某些顶点。

参数: 

:

输入图。 它可以是有向图,但边缘方向将被忽略。

candidate:

候选分隔符。

res:

指向布尔变量的指针,结果存储在这里。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),与顶点和边的数量呈线性关系。

示例 23.1.  文件 examples/simple/igraph_is_separator.c

#include <igraph.h>
#include <stdio.h>

#define FAIL(msg, error) do { printf(msg "\n") ; return error; } while (0)

int main(void) {

    igraph_t graph;
    igraph_vector_int_t sep;
    igraph_bool_t result;

    /* Simple star graph, remove the center */
    igraph_star(&graph, 10, IGRAPH_STAR_UNDIRECTED, 0);
    igraph_is_separator(&graph, igraph_vss_1(0), &result);
    if (!result) {
        FAIL("Center of star graph failed.", 1);
    }

    /* Same graph, but another vertex */
    igraph_is_separator(&graph, igraph_vss_1(6), &result);
    if (result) {
        FAIL("Non-center of star graph failed.", 2);
    }

    /* Same graph, all vertices but the center */
    igraph_is_separator(&graph, igraph_vss_range(1, 10), &result);
    if (result) {
        FAIL("All non-central vertices of star graph failed.", 5);
    }

    /* Same graph, all vertices */
    igraph_is_separator(&graph, igraph_vss_range(0, 10), &result);
    if (result) {
        FAIL("All vertices of star graph failed.", 6);
    }
    igraph_destroy(&graph);

    /* Karate club */
    igraph_famous(&graph, "zachary");
    igraph_vector_int_init(&sep, 0);
    igraph_vector_int_push_back(&sep, 32);
    igraph_vector_int_push_back(&sep, 33);
    igraph_is_separator(&graph, igraph_vss_vector(&sep), &result);
    if (!result) {
        FAIL("Karate network (32,33) failed", 3);
    }

    igraph_vector_int_resize(&sep, 5);
    VECTOR(sep)[0] = 8;
    VECTOR(sep)[1] = 9;
    VECTOR(sep)[2] = 19;
    VECTOR(sep)[3] = 30;
    VECTOR(sep)[4] = 31;
    igraph_is_separator(&graph, igraph_vss_vector(&sep), &result);
    if (result) {
        FAIL("Karate network (8,9,19,30,31) failed", 4);
    }

    igraph_destroy(&graph);
    igraph_vector_int_destroy(&sep);

    return 0;
}


2. igraph_is_minimal_separator — 确定一组顶点是否是最小分隔符。

igraph_error_t igraph_is_minimal_separator(const igraph_t *graph,
                                           const igraph_vs_t candidate,
                                           igraph_bool_t *res);

顶点分隔符 S 是最小的,当且仅当 S 的任何真子集都不是分隔符。

参数: 

:

输入图。 它可以是有向图,但边缘方向将被忽略。

candidate:

候选的最小分隔符。

res:

指向布尔变量的指针,结果存储在这里。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),与顶点和边的数量呈线性关系。

示例 23.2.  文件 examples/simple/igraph_is_minimal_separator.c

#include <igraph.h>
#include <stdio.h>

#define FAIL(msg, error) do { printf(msg "\n") ; return error; } while (0)

int main(void) {

    igraph_t graph;
    igraph_vector_int_t sep;
    igraph_bool_t result;

    /* Simple star graph, remove the center */
    igraph_star(&graph, 10, IGRAPH_STAR_UNDIRECTED, 0);
    igraph_is_minimal_separator(&graph, igraph_vss_1(0), &result);
    if (!result) {
        FAIL("Center of star graph failed.", 1);
    }

    /* Same graph, but another vertex */
    igraph_is_minimal_separator(&graph, igraph_vss_1(6), &result);
    if (result) {
        FAIL("Non-center of star graph failed.", 2);
    }
    igraph_destroy(&graph);

    /* Karate club */
    igraph_famous(&graph, "zachary");
    igraph_vector_int_init(&sep, 0);
    igraph_vector_int_push_back(&sep, 32);
    igraph_vector_int_push_back(&sep, 33);
    igraph_is_minimal_separator(&graph, igraph_vss_vector(&sep), &result);
    if (!result) {
        FAIL("Karate network (32,33) failed", 3);
    }

    igraph_vector_int_resize(&sep, 5);
    VECTOR(sep)[0] = 8;
    VECTOR(sep)[1] = 9;
    VECTOR(sep)[2] = 19;
    VECTOR(sep)[3] = 30;
    VECTOR(sep)[4] = 31;
    igraph_is_minimal_separator(&graph, igraph_vss_vector(&sep), &result);
    if (result) {
        FAIL("Karate network (8,9,19,30,31) failed", 4);
    }

    igraph_destroy(&graph);
    igraph_vector_int_destroy(&sep);

    return 0;
}


3. igraph_all_minimal_st_separators — 列出所有对于某些 s 和 t 来说是最小 (s,t) 分隔符的顶点集。

igraph_error_t igraph_all_minimal_st_separators(
    const igraph_t *graph, igraph_vector_int_list_t *separators
);

此函数列出所有对于某些 (s,t) 顶点对来说是最小 (s,t) 分隔符的顶点集。

请注意,此函数返回的某些顶点集可能不是断开图(或增加连通分量的数量)的最小顶点集。例如,考虑具有边 0-1-2-3-4-1 的 5 顶点图。此函数返回顶点集 {1}{2,4}{1,3}。请注意,{1,3} 对于断开图来说不是最小的,因为 {1} 就足够了。但是,它对于分隔顶点 24 来说是最小的。

有关已实现算法的更多信息,请参见 Anne Berry, Jean-Paul Bordat and Olivier Cogis: Generating All the Minimal Separators of a Graph, In: Peter Widmayer, Gabriele Neyer and Stephan Eidenbenz (editors): Graph-theoretic concepts in computer science, 1665, 167--172, 1999. Springer. https://doi.org/10.1007/3-540-46784-X_17

参数: 

:

输入图。 它可以是有向图,但边缘方向将被忽略。

separators:

指向整数向量列表的指针,分隔符将存储在此处。

返回值: 

错误代码。

另请参阅: 

时间复杂度:O(n|V|^3), |V| 是顶点的数量,n 是分隔符的数量。

示例 23.3.  文件 examples/simple/igraph_minimal_separators.c

#include <igraph.h>
#include <stdio.h>

int main(void) {
    igraph_t graph;
    igraph_vector_int_list_t separators;
    igraph_integer_t i, n;

    igraph_famous(&graph, "zachary");
    igraph_vector_int_list_init(&separators, 0);
    igraph_all_minimal_st_separators(&graph, &separators);

    n = igraph_vector_int_list_size(&separators);
    for (i = 0; i < n; i++) {
        igraph_bool_t res;
        igraph_vector_int_t *sep = igraph_vector_int_list_get_ptr(&separators, i);

        igraph_is_separator(&graph, igraph_vss_vector(sep), &res);
        if (!res) {
            printf("Vertex set %" IGRAPH_PRId " is not a separator!\n", i);
            igraph_vector_int_print(sep);
            return 1;
        }
    }

    igraph_destroy(&graph);
    igraph_vector_int_list_destroy(&separators);

    return 0;
}


4. igraph_minimum_size_separators — 查找所有最小大小的分隔顶点集。

igraph_error_t igraph_minimum_size_separators(
    const igraph_t *graph, igraph_vector_int_list_t *separators
);

此函数列出所有最小大小的分隔顶点集。如果移除顶点集会断开图,则该顶点集是分隔符。

该实现基于以下论文:Arkady Kanevsky: Finding all minimum-size separating vertex sets in a graph, Networks 23, 533--541, 1993. https://doi.org/10.1002/net.3230230604

参数: 

:

输入图,必须是无向图。

separators:

已初始化的整数向量列表,分隔符存储在此处。它是指向 igraph_vector_int_t 对象的指针列表。每个向量将包含分隔符中顶点的 ID。分隔符以任意顺序返回。

返回值: 

错误代码。

时间复杂度:待定。

示例 23.4.  文件 examples/simple/igraph_minimum_size_separators.c

#include <igraph.h>

int main(void) {
    igraph_t g;
    igraph_vector_int_list_t sep;

    igraph_small(&g, 7, IGRAPH_UNDIRECTED,
                 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0,
                 -1);
    igraph_vector_int_list_init(&sep, 0);
    igraph_minimum_size_separators(&g, &sep);

    for (igraph_integer_t i = 0; i < igraph_vector_int_list_size(&sep); i++) {
        igraph_vector_int_t* v = igraph_vector_int_list_get_ptr(&sep, i);
        igraph_vector_int_print(v);
    }

    igraph_vector_int_list_destroy(&sep);
    igraph_destroy(&g);

    return 0;
}


5. igraph_even_tarjan_reduction — 图的 Even-Tarjan 归约。

igraph_error_t igraph_even_tarjan_reduction(const igraph_t *graph, igraph_t *graphbar,
        igraph_vector_t *capacity);

创建一个有向图,其顶点和边的数量是原来的两倍。对于每个原始顶点 i,创建两个顶点 i' = ii'' = i' + n,并从 i'i'' 存在一条有向边。对于从 ij 的每个原始有向边,创建两个新边,从 i'j'' 和从 i''j'

此归约用于论文(观察 2):Arkady Kanevsky: Finding all minimum-size separating vertex sets in a graph, Networks 23, 533--541, 1993.

构思此归约的原始论文是 Shimon Even 和 R. Endre Tarjan: Network Flow and Testing Graph Connectivity, SIAM J. Comput., 4(4), 507–518. https://doi.org/10.1137/0204043

参数: 

:

一个图。虽然不检查方向性,但此函数通常仅用于有向图。

graphbar:

指向新有向图的指针,该图将包含归约,其顶点和边的数量是原来的两倍。

capacity:

指向已初始化的向量或空指针的指针。如果不是空指针,则将填充归约的容量:前 |E| 个元素为 1,其余 |E| 个元素等于 |V|(用于表示无穷大)。

返回值: 

错误代码。

时间复杂度:O(|E|+|V|)。

示例 23.5.  文件 examples/simple/even_tarjan.c

#include <igraph.h>
#include <limits.h>

int main(void) {

    igraph_t g, gbar;
    igraph_integer_t k1, k2 = INT_MAX;
    igraph_real_t tmpk;
    igraph_integer_t i, j, n;
    igraph_maxflow_stats_t stats;

    /* --------------------------------------------------- */

    igraph_famous(&g, "meredith");
    igraph_even_tarjan_reduction(&g, &gbar, /*capacity=*/ NULL);

    igraph_vertex_connectivity(&g, &k1, /* checks= */ false);

    n = igraph_vcount(&g);
    for (i = 0; i < n; i++) {
        for (j = i + 1; j < n; j++) {
            igraph_bool_t conn;
            igraph_are_adjacent(&g, i, j, &conn);
            if (conn) {
                continue;
            }
            igraph_maxflow_value(&gbar, &tmpk,
                                 /* source= */ i + n,
                                 /* target= */ j,
                                 /* capacity= */ 0,
                                 &stats);
            if (tmpk < k2) {
                k2 = tmpk;
            }
        }
    }

    igraph_destroy(&gbar);
    igraph_destroy(&g);

    if (k1 != k2) {
        printf("k1 = %" IGRAPH_PRId " while k2 = %" IGRAPH_PRId "\n", k1, k2);
        return 1;
    }

    return 0;
}