有向图的最长路径及是否存在环路结构

来源:互联网 发布:索尼笔记本知乎 编辑:程序博客网 时间:2024/06/07 04:30

问题描述:

有n个长为m+1的字符串,如果某个字符串的最后m个字符与某个字符串的前m个字符匹配,则两个字符串可以连接。问这n个字符串最多可以连成一个多长的字符串,如果出现循环,则返回错误。

分析:

把每个字符串看成一个图的顶点,两个字符串可以连接就形成一条有向边。相当于判断一个有向图是否存在环以及求该有向图的最长路径。

可用图的深度优先遍历算法来求解,图用邻接表表示。

 

1. 求解有向图是否存在环及最长路径

#define VERTEX_NUM7#define NOT_VISITED-1//该顶点未被访问#define VISITED0//该顶点已经被访问,但它的邻接点未被访问完成#define FINISHED1//结束访问该顶点的邻接表#define IS_CIRCLE-1int maxLen = -1;int getMaxLenInGraph(int adj[][VERTEX_NUM]); //返回-1表示该有向图中存在环路int DFS_VISTI(int state[], int adj[][VERTEX_NUM], int i, int *len); //深度优先遍历int getMaxLenInGraph(int adj[][VERTEX_NUM]){int state[VERTEX_NUM];for (int i = 0; i < VERTEX_NUM; i++)state[i] = NOT_VISITED;int tempLen;for (int i = 0; i < VERTEX_NUM; i++){tempLen = 0;if (state[i] == NOT_VISITED){if (DFS_VISTI(state, adj, i, &tempLen) == IS_CIRCLE)return IS_CIRCLE;}}return maxLen;}//state[i]存储顶点i的状态,adj[i][]数组中存储所有与顶点i相邻的顶点int DFS_VISTI(int state[], int adj[][VERTEX_NUM], int i, int *len){state[i] = VISITED;for (int j = 1; adj[i][j] != -1; j++){if (state[adj[i][j]] == NOT_VISITED){(*len)++;if (DFS_VISTI(state, adj, adj[i][j], len) == IS_CIRCLE)return IS_CIRCLE;}else if (state[adj[i][j]] == VISITED)//这样表示环的存在,经得起考验吗?{*len = IS_CIRCLE;return IS_CIRCLE;}}state[i] = FINISHED;if (*len > maxLen)maxLen = *len;*len = 0;return 0;}

 

测试代码:

int main(){//图的邻接表数据,-1表示结束int Adj[VERTEX_NUM][VERTEX_NUM] = {{0, 1, 3, -1},{1, 2, 3, 4, -1},{2, 3, 4, 5, -1},{3, 4, -1},{4, 5, -1},{5, 6, -1},{6, -1}//改为6, 0, -1 则表示存在环};int len = getMaxLenInGraph(Adj);printf("the length of graphic is : %d\n", len);system("pause");return 0;}



2.求解能连接成的最长字符串( 首先建图,然后利用上面提供的函数即可求解 )

代码实现如下:

#include <iostream>#include <string>using namespace std;#define VERTEX_NUM8#define NOT_VISITED-1//该顶点未被访问#define VISITED0//该顶点已经被访问,但它的邻接点未被访问完成#define FINISHED1//结束访问该顶点的邻接表#define IS_CIRCLE-1int maxLen = -1;int getMaxLenInGraph(int adj[][VERTEX_NUM]); //返回-1表示该有向图中存在环路int DFS_VISTI(int state[], int adj[][VERTEX_NUM], int i, int *len); //深度优先遍历void build_graph(string str[], int graph[][VERTEX_NUM]);int main(){string str[] = {"abc", "bcf", "cfg", "fga", "gam", "bcg", "cga", "gai",};//其邻接表,若改变4节点为"gab",则出现循环//0-1-5//1-2//2-3//3-4-7//4//5-6//6-4-7//7int Graph[VERTEX_NUM][VERTEX_NUM];//构造图的邻接表build_graph(str, Graph);int len = getMaxLenInGraph(Graph);printf("该有向图最长路径为(-1表示存在环): %d\n", len);if (len != -1)printf("可以连接成的最长字符串为:%d\n", str[0].length()+len);system("pause");return 0;}void build_graph(string str[], int gra[][VERTEX_NUM]){for (int i = 0; i < VERTEX_NUM; i++)for (int j = 0; j < VERTEX_NUM; j++){if (j == 0)gra[i][j] = i;elsegra[i][j] = -1;}int index;for (int i = 0 ; i < VERTEX_NUM; i++){index = 1;string suffix = str[i].substr(1);for (int j = 0; j < VERTEX_NUM; j++){if (str[j].find(suffix) == 0)gra[i][index++] = j;}}}

 

出现问题在所难免,如有发现错误的朋友,请指正!

注:运行时会提示栈溢出的问题,修改property->configuration properties -> linker -> system中的stack reserve size和 stack commit size即可~

原创粉丝点击