【编程题目】求一个有向连通图的割点,割点的定义是,如果除去此节点和与其相关的边, 有向图不再连通

39.(树、图、算法)
(2).
求一个有向连通图的割点,割点的定义是,如果除去此节点和与其相关的边,
有向图不再连通,描述算法。

思路:这里有个问题,对于图的连通性,我默认它要求强连通。采用了最简单的办法,即每次删掉一条边,判断图还是否连通。若变得不连通了就认为此点是割点。

连通性的判断也采用了直觉上简单的方法,就是对每一个点判断是否有向内指向它的边和它向外指向的边。(question:如此直观的方法是否会有错呢?)

/*
39.(树、图、算法)
(2).
求一个有向连通图的割点,割点的定义是,如果除去此节点和与其相关的边,
有向图不再连通,描述算法。
*/

#include <stdio.h>

#define MAX_VERTEX_NUM 20
#define INFINITY 10000

typedef struct ArcCell{
    int adj;
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct MGraph{
    int vexs[MAX_VERTEX_NUM];
    AdjMatrix arcs;
    int vexnum, arcnum;
}MGraph;

//定位顶点
int LocateVex(MGraph G, int v)
{
    for(int i = 0; i < G.vexnum; i++)
    {
        if(G.vexs[i] == v)
            return i;
    }
    return -1; //means error
}
void CreateDN(MGraph &G) //生成有向图
{
    printf("Input the vexnum:");
    scanf("%d",&G.vexnum);
    printf("Input the arcnum:");
    scanf("%d", &G.arcnum);

    for(int i = 0; i < G.vexnum; i++)
    {
        printf("Input the %d vex:", i);
        scanf("%d", &G.vexs[i]);
    }

    for(int i = 0; i < G.vexnum; i++)
        for(int j = 0; j < G.vexnum; j++)
            G.arcs[i][j].adj = INFINITY;

    for(int k = 0; k < G.arcnum; k++)
    {
        int v1, v2, w;
        printf("input the arcs vex and weight:");
        scanf("%d %d %d", &v1, &v2, &w);
        int i = LocateVex(G, v1);
        int j = LocateVex(G, v2);
        G.arcs[i][j].adj = w;
    }
}

//有向图是否强连通
bool isConnected(MGraph G)
{
    bool connected = true;
    for(int i = 0; i < G.vexnum; i++)
    {
        bool haveConnectedIn = false;
        bool haveConnectedOut = false;
        for(int j = 0; j < G.vexnum; j++)
        {
            if(G.arcs[i][j].adj < INFINITY)
                haveConnectedOut = true;
            if(G.arcs[j][i].adj < INFINITY)
                haveConnectedIn = true;
        }

        if(haveConnectedOut != true || haveConnectedIn != true)
        {
            connected = false;
            break;
        }
    }

    return connected;
}

//得到有向图G去掉一个顶点和其相邻边后的图
MGraph deleteOneVex(MGraph G, int vex)
{
    MGraph DG;
    DG.vexnum = G.vexnum - 1;
    int j = 0;
    for(int i = 0; i < G.vexnum; i++)
    {
        if(i != vex)
        {
            DG.vexs[j++] = G.vexs[i];
        }
    }

    DG.arcnum = 0;
    for(int i = 0; i < G.vexnum; i++)
        for(int j = 0; j < G.vexnum; j++)
            if(i != vex && j != vex)
            {
                int v = (i > vex) ? i - 1 : i;
                int u = (j > vex) ? j - 1 : j;
                DG.arcs[v][u].adj = G.arcs[i][j].adj;
                DG.arcnum++;
            }

    return DG;
}

//查找图的割
void GetGutSet(MGraph G)
{
    bool isconnect = isConnected(G);
    if(isconnect == false)
    {
        printf("the Graph is not connected.\n");
        return;
    }

    int n = 0;
    if(G.vexnum < 1)
    {
        printf("no vex");
    }
    else if(G.vexnum == 1)
    {
        printf("cut is %d\n", G.vexs[0]);
    }
    else
    {
        for(int i = 0 ; i < G.vexnum; i++)
        {
            MGraph DG = deleteOneVex(G, i);
            bool isconnect = isConnected(DG);
            if(isconnect == false)
            {
                printf("The %d cut vex is %d\n", n, G.vexs[i]);
            }
        }
    }
}

int main()
{
    MGraph G;
    CreateDN(G);
    GetGutSet(G);

    return 0;
}

网上看到有专门的算法,还在学习。

时间: 2024-12-15 07:22:31

【编程题目】求一个有向连通图的割点,割点的定义是,如果除去此节点和与其相关的边, 有向图不再连通的相关文章

【编程题目】一个数组是由一个递减数列左移若干位形成的,在这种数组中查找某一个数。☆

48.微软(运算):一个数组是由一个递减数列左移若干位形成的,比如{4,3,2,1,6,5}是由{6,5,4,3,2,1}左移两位形成的,在这种数组中查找某一个数. 我的思路: 非常麻烦:先是用二分法找最大的数的位置,再定位要找的数在哪个递减区间里,最后用普通的二分查找法找到.代码如下: /* 48.微软(运算): 一个数组是由一个递减数列左移若干位形成的,比如{4,3,2,1,6,5} 是由{6,5,4,3,2,1}左移两位形成的,在这种数组中查找某一个数. */ #include <stdi

【目录】编程题目

编程题目 如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1) 一个数组是由一个递减数列左移若干位形成的,在这种数组中查找某一个数.☆ 请修改 append 函数,利用这个函数实现两个非降序链表的并集 一串首尾相连的珠子(m 个),有 N 种颜色(N<=10),取出其中一段,要求包含所有 N 中颜色,并使长度最短. 求一个有向连通图的割点,割点的定义是,如果除去此节点和与其相关的边, 有向图不再连通 有 n 个长为 m+1 的字符串,如果某个字符串的最后 m 个字符与某个字符串的前

【编程题目】求一个矩阵中最大的二维矩阵(元素和最大)

35.(矩阵)求一个矩阵中最大的二维矩阵(元素和最大).如:1 2 0 3 42 3 4 5 11 1 5 3 0中最大的是:4 55 3要求:(1)写出算法;(2)分析时间复杂度;(3)用 C 写出关键代码 早上灭小题! /* 35.(矩阵) 求一个矩阵中最大的二维矩阵(元素和最大).如: 1 2 0 3 4 2 3 4 5 1 1 1 5 3 0 中最大的是: 4 5 5 3 要求:(1)写出算法;(2)分析时间复杂度;(3)用 C 写出关键代码 */ #include <stdio.h>

【编程题目】求一个数组的最长递减子序列 比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5, 4,3,2}

47.创新工场(算法):求一个数组的最长递减子序列 比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2} 思路:动态规划 从最后一个数字开始,计算以当前数字其实的序列的最长递减子序列. 每次找最长子序列,都扫描它之前求得的子序列中最长,且第一个数字比当前数字小的. 如: 第一个数字 2, 最大长度 1, 下一个数字是 第 7 个 第二个数字 3,  最大长度 2, 下一个数字是 第 7 个 第三个数字 4,  最大长度 3, 下一个数字是 第 6 个 第四个数字 5, 

【编程题目】n 个数字(0,1,…,n-1)形成一个圆圈,从数字 0 开始

第 18 题(数组):题目:n 个数字(0,1,…,n-1)形成一个圆圈,从数字 0 开始,每次从这个圆圈中删除第 m 个数字(第一个为当前数字本身,第二个为当前数字的下一个数字).当一个数字删除后,从被删除数字的下一个继续删除第 m 个数字.求出在这个圆圈中剩下的最后一个数字. 思路:看到这道题,直觉是不难,模拟一下过程就好了.我用的是数组来表示的,用first表示当前第一个数字是哪一个数,若删除一个数字则将后面的数字平移到前面. /* 第 18 题(数组): 题目:n 个数字(0,1,…,n

【编程题目】求1+2+…+n, 要求不能使用乘除法、for、while、if、else、switch、case和条件语句

看到这个问题,第一个反应是真变态啊. 然后,直觉是不能用循环就只能用递归了.可递归怎么跳出来却遇到了麻烦, 我连goto语句都考虑了也没弄好. 后来想到一个非常NC的方法:查找表. 如果n限定一个比较小的范围直接用查找表好了. 但题目的目的肯定不是这样的..... 后来,我转换了一下思路 1+2...+n = (n*n + n)>>1  只要求出n*n来就好了, 但问题是不能用乘法,于是硬件出身的我想到了二进制&,|,>>,<<都是可以用的. 思路:设n = 5

【编程题目】对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)某一个元素也加一

45.雅虎(运算.矩阵):1.对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)某一个元素也加一,现给出一正数矩阵,判断其是否能够由一个全零矩阵经过上述运算得到. 这道题,是我目前为止做过的最最最最最麻烦.最繁琐的题目了. 思路: 把输入的矩阵一步步还原成 0 矩阵 一个数字,只可能伴随着它上下左右四个方向的数字变化. ①如果数字比它周围四个数的和要大,那么一定不满足条件. ②如果数字小于等于四周的数字和,且其四周仅有一个数字不为0: 不为0的那个周围数字的大小 -=

【编程题目】输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。

第 14 题(数组):题目:输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字.要求时间复杂度是 O(n).如果有多对数字的和等于输入的数字,输出任意一对即可.例如输入数组 1.2.4.7.11.15 和数字 15.由于 4+11=15,因此输出 4 和 11. 要求时间是O(n)肯定就只能扫描一遍. 又有两个数字要找,那就只能一个从头向后找 一个从后向前找 初始把大值设为最后一个数, 小值设为第一个数,如果数字和大于和,则减小大数的数值, 反之增大小

题目1545:奇怪的连通图

奇怪的连通图 题目描述: 已知一个无向带权图,求最小整数k.使仅使用权值小于等于k的边,节点1可以与节点n连通. 输入: 输入包含多组测试用例,每组测试用例的开头为一个整数n(1 <= n <= 10000),m(1 <= m <= 100000),代表该带权图的顶点个数,和边的个数.接下去m行,描述图上边的信息,包括三个整数,a(1 <= a <= n),b(1 <= b <= n),c(1 <= c <= 1000000),表示连接顶点a和顶