当前位置 博文首页 > Jason ZHANG的博客:独立路径计算
【问题描述】
老张和老王酷爱爬山,每周必爬一次香山。有次两人为从东门到香炉峰共有多少条路径发生争执,于是约定一段时间内谁走过对方没有走过的路线多谁胜。
给定一线路图(无向连通图,两顶点之间可能有多条边),编程计算从起始点至终点共有多少条独立路径,并输出相关路径信息。
注:独立路径指的是从起点至终点的一条路径中至少有一条边是与别的路径中所不同的,同时路径中不存在环路。
?
【输入形式】
图的顶点按照自然数(0,1,2,…n)进行编号,其中顶点0表示起点,顶点n-1表示终点。从标准输入中首先输入两个正整数n,e,分别表示线路图的顶点的数目和边的数目,然后在接下的e行中输入每条边的信息,具体形式如下:
<n> <e>
<e1> <vi1> <vj1>
<e2> <vi2> <vj2>
…
<en> <vin> <vjn>
说明:第一行<n>为图的顶点数,<e>表示图的边数;第二行<e1> <vi1> <vj1>分别为边的序号(边序号的范围在[0,1000)之间,即包括0不包括1000)和这条边的两个顶点(两个顶点之间有多条边时,边的序号会不同),中间由一个空格分隔;其它类推。
【输出形式】
输出从起点0到终点n-1的所有路径(用边序号的序列表示路径且路径中不能有环),每行表示一条由起点到终点的路径(由边序号组成,中间有一个空格分隔,最后一个数字后跟回车),并且所有路径按照字典序输出。
【样例输入】
6 8
1 0 1
2 1 2
3 2 3
4 2 4
5 3 5
6 4 5
7 0 5
8 0 1
【样例输出】
1 2 3 5
1 2 4 6
7
8 2 3 5
8 2 4 6
【样例说明】
样例输入构成的图如下:
输出的第一个路径1 2 3 5,表示一条路径,先走1号边(顶点0到顶点1),然后走2号边(顶点1到顶点2),然后走3号边(顶点2到顶点3),然后走5号边(顶点3到顶点5)到达终点。
#include <stdio.h>
#include <string.h>
typedef struct _Edge
{
int adjvex;
int seq;
struct _Edge *next;
} Edge;
typedef struct _Vertex
{
int seq;
Edge *link;
} Vertex;
typedef struct _Adjlist
{
int size;
Vertex *list;
} Adjlist;
Adjlist *create_Adjlist(int n)
{
int i;
Adjlist *adjlist = (Adjlist *)malloc(sizeof(Adjlist));
adjlist->list = (Vertex *)malloc(n*sizeof(Vertex));
adjlist->size = n;
for (i = 0; i < n; i++)
{
adjlist->list[i].seq = i;
adjlist->list[i].link = NULL; // mark the rear
}
return adjlist;
}
void insert_Edge(int seq, Vertex *head, int end)
{
Edge *rear = head->link;
Edge *newEdge = (Edge *)malloc(sizeof(Edge));
newEdge->seq = seq;
newEdge->adjvex = end;
newEdge->next = NULL;
if (rear == NULL)
{
head->link = newEdge;
}
else
{
while (rear->next != NULL) rear = rear->next; // reach the rear
rear->next = newEdge; // add the new Edge at the rear
}
}
void print_Path(int path[])
{
int i = 0;
while (path[i + 1] != 0)
printf("%d ", path[i++]);
printf("%d\n", path[i]);
}
void DFS(int start, int depth, Adjlist adjlist, int path[], int visited[])
{
if (start == adjlist.size - 1)
{
path[depth] = 0; // mark the end of the path
print_Path(path);
return;
}
else
{
if (!visited[start]) // no loop in a path, thus no vertex should be visited twice
{
visited[start] = 1; // if not visited before, now mark it as visited
Edge *link = adjlist.list[start].link;
while (link != NULL)
{
path[depth] = link->seq; // mark the edge as a step in the path
DFS(link->adjvex, depth + 1, adjlist, path, visited); // the next start is the vertex the current vertex leads to
link = link->next; // search the next vertex the current vertex leads to
}
visited[start] = 0; // de-visit this vertex so that after quitting other searching can reach this vertex again
return;
}
}
}
void iterate_Path(Adjlist adjlist)
{
int *path = (int *)malloc(adjlist.size*sizeof(int)); // a path cannot be longer than the number of vertexes
int *visited = (int *)malloc(adjlist.size*sizeof(int));
memset(visited, 0, adjlist.size*sizeof(int)); // mark all vertexes as unvisited
DFS(0, 0, adjlist, path, visited);
free(path);
free(visited);
}
int main()
{
Adjlist *adjlist;
int n, e;
int seq,v1,v2,i;
scanf("%d %d",&n, &e);
adjlist = create_Adjlist(n);
for (i = 0; i < e; i++)
{
scanf("%d %d %d",&seq,&v1,&v2);
insert_Edge(seq, &(adjlist->list[v1]), v2);
insert_Edge(seq, &(adjlist->list[v2]), v1);
}
iterate_Path(*adjlist);
return 0;
}