我暂时没找到好的方法,只能暴力,也没有找到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;
}