找所有简单回路

我暂时没找到好的方法,只能暴力,也没有找到oj可以A题,所以也不知道代码对不对

下面的代码,只针对简单图

基本思路就是找回路,判重,回溯

有向图

#include<iostream>
#include<cstring>
using namespace std;
const int N = 1005, M = 1005;
typedef struct ArcNode {
    int arcvex;
    struct ArcNode* next;
}ArcNode;
typedef struct {
    ArcNode* first;
}VertexNode;
typedef struct {
    VertexNode adList[N];
    int vertex_num;
}ALGraph;
typedef struct {
    int data[N];
    int length;
}List;
List cycles[M];//所有回路
int path_num; //找到回路个数
bool visit[N]; //是否访问过
int path[N]; //临时路径
void init(ALGraph& G) {
    for (int i = 0; i < N; ++i) {
        G.adList[i].first = NULL;
    }
}
void destroy(ALGraph& G) {
    for (int i = 0; i < N; ++i) {
        ArcNode* p = G.adList[i].first;
        while (p != NULL) {
            ArcNode* temp = p->next;
            delete p;
            p = temp;
        }
        G.adList[i].first = NULL;
    }
}
void add_edge(ALGraph& G, int u, int v) {
    ArcNode* p = new ArcNode;
    p->arcvex = v;
    p->next = G.adList[u].first;
    G.adList[u].first = p;
}
/**
 * 判断是否已经存在这条路径
 * @param start path中开始下标
 * @param end path中结束下标+1
 * @return true是|false否
 */
bool check_exists(int start, int end) {
    int path_length = end - start;//路径长度
    for (int i = 0; i < path_num; ++i) {
        if (path_length != cycles[i].length) { //长度不等
            continue;
        }
        //找起点位置
        int start_id = 0;
        while (start_id < cycles[i].length && cycles[i].data[start_id] != path[start]) {
            ++start_id;
        }
        if (start_id == cycles[i].length) {//没找到
            continue;
        }
        int j;
        //比较是否相同
        for (j = 1; j < path_length; ++j) {
            if (cycles[i].data[(start_id + j) % path_length] != path[start + j]) {
                break;
            }
        }
        if (j == path_length) {//找到了相同
            return true;
        }
    }
    return false;
}
/**
 * 深度优先遍历
 * @param G 有向图邻接表
 * @param u 当前节点
 * @param k 路径长度
 */
void dfs(ALGraph& G, int u, int k) {
    visit[u] = true;
    path[k++] = u;
    for (ArcNode* p = G.adList[u].first; p != NULL; p = p->next) {
        int v = p->arcvex;
        if (visit[v]) {
            //找回路起点下标
            int start = 0;
            while (start < k && path[start] != v) {
                ++start;
            }

            if (start < k && !check_exists(start, k)) {
                int path_length = k - start;
                for (int i = 0; i < path_length; ++i) {
                    cycles[path_num].data[i] = path[start + i];
                }
                cycles[path_num++].length = path_length;
            }

        }
        else {
            dfs(G, v, k);
        }
    }
    visit[u] = false;
}
/**
 * 找到所有简单回路
 * @param G 有向图邻接表
 * @param n 顶点数
 */
void find_all_cycles(ALGraph& G) {
    path_num = 0;
    memset(visit, false, sizeof(visit));
    for (int i = 1; i <= G.vertex_num; ++i) {
        if (!visit[i]) {
            dfs(G, i, 0);
        }
    }
    for (int i = 0; i < path_num; ++i) {
        for (int j = 0; j < cycles[i].length; ++j) {
            printf("%d", cycles[i].data[j]);
            if (j + 1 < cycles[i].length) {
                printf(" ");
            }
            else {
                printf("\n");
            }
        }
    }
}
int main() {
    int n, m;
    while (~scanf("%d%d", &n, &m)) {
        ALGraph G;
        G.vertex_num = n;
        init(G);
        while (m--) {
            int u, v;
            scanf("%d%d", &u, &v);
            add_edge(G, u, v);
        }
        find_all_cycles(G);
        destroy(G);
    }
    return 0;
}

无向图

要防止0->1 ->0这种

#include<iostream>
#include<cstring>
using namespace std;
const int N = 1005, M = 1005;
typedef struct ArcNode {
    int arcvex;
    struct ArcNode* next;
}ArcNode;
typedef struct {
    ArcNode* first;
}VertexNode;
typedef struct {
    VertexNode adList[N];
    int vertex_num;
}ALGraph;
void init(ALGraph& G) {
    for (int i = 0; i < N; ++i) {
        G.adList[i].first = NULL;
    }
}
void destroy(ALGraph& G) {
    for (int i = 0; i < N; ++i) {
        ArcNode* p = G.adList[i].first;
        while (p != NULL) {
            ArcNode* temp = p->next;
            delete p;
            p = temp;
        }
        G.adList[i].first = NULL;
    }
}
void add_edge(ALGraph& G, int u, int v) {
    ArcNode* p = new ArcNode;
    p->arcvex = v;
    p->next = G.adList[u].first;
    G.adList[u].first = p;
}
//vector
typedef struct {
    int data[N];
    int length;
}Array;
Array cycles[M]; //所有的回路
int cycle_num; //回路数量
int path[N]; //当前路径
bool visit[N]; //访问
/**
 * 判断是否找到过这个回路
 * @param start 开始下标
 * @param end 结束下标+1
 * @return true找到|false没找到
 */
bool find_cycle(int start, int end) {
    int length = end - start;
    for (int i = 0; i < cycle_num; ++i) {
        if (length != cycles[i].length) {//回路长度不一样
            continue;
        }
        int start_id = 0;
        //找开始下标
        while (start_id < cycles[i].length && cycles[i].data[start_id] != path[start]) {
            ++start_id;
        }
        if (start_id == cycles[i].length) {//没找到
            continue;
        }
        int j = 1;
        //正着对一遍0->1->2->3->0
        while (j < length && cycles[i].data[(start_id + j) % length] == path[start + j]) {
            ++j;
        }
        if (j == length) {//相同
            return true;
        }
        j = 1;
        //反着对一遍0->3->2->1->0
        while (j < length && cycles[i].data[(start_id - j + length) % length] == path[start + j]) {
            ++j;
        }
        if (j == length) {//相同
            return true;
        }
    }
    return false;
}
/**
 * 深度优先遍历
 * @param G 无向图邻接表
 * @param u 当前顶点
 * @param k 路径长度
 */
void dfs(ALGraph& G, int u, int k) {
    visit[u] = true;
    path[k++] = u;
    for (ArcNode* p = G.adList[u].first; p != NULL; p = p->next) {
        int v = p->arcvex;
        if (visit[v]) {//访问过
            int start_id = 0;
            //找回路开始下标
            while (start_id < k && path[start_id] != v) {
                ++start_id;
            }
            int length = k - start_id;
            //判断是否找到过,q且不能是0->1->0这种
            if (start_id < k && length>2 && !find_cycle(start_id, k)) {
                //添加
                for (int i = 0; i < length; ++i) {
                    cycles[cycle_num].data[i] = path[start_id++];
                }
                cycles[cycle_num++].length = length;
            }
        }
        else {
            dfs(G, v, k);
        }
    }
    visit[u] = false;//回溯
}
/**
 * 找到所有简单回路
 * @param G 无向图邻接表
 */
void find_all_cycles(ALGraph& G) {
    memset(visit, false, sizeof(visit));
    cycle_num = 0;
    for (int i = 0; i < G.vertex_num; ++i) {
        if (!visit[i]) {
            dfs(G, i, 0);
        }
    }
    for (int i = 0; i < cycle_num; ++i) {
        for (int j = 0; j < cycles[i].length; ++j) {
            printf("%d", cycles[i].data[j]);
            if (j + 1 == cycles[i].length) {
                printf("\n");
            }
            else {
                printf(" ");
            }
        }
    }
}
int main() {
    int n, m;
    while (~scanf("%d%d", &n, &m)) {
        ALGraph G;
        init(G);
        G.vertex_num = n;
        while (m--) {
            int u, v;
            scanf("%d%d", &u, &v);
            add_edge(G, u, v);
            add_edge(G, v, u);
        }
        find_all_cycles(G);
        destroy(G);
    }
    return 0;
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nightmare004

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值