本文用纯C语言来编写,适合初学者,编译环境是Code::Blocks。
问题描述
为了增加公司收入,F 公司新开设了物流业务。由于 F 公司在业界的
良好口碑,物流业务一开通即受到了消费者的欢迎,物流业务马上遍及了
城市的每条街道。然而,F 公司现在只安排了小明一个人负责所有街道的
服务。
任务虽然繁重,但是小明有足够的信心,他拿到了城市的地图,准备
研究最好的方案。城市中有 n 个交叉路口,m 条街道连接在这些交叉路口
之间,每条街道的首尾都正好连接着一个交叉路口。除开街道的首尾端点,
街道不会在其他位置与其他街道相交。每个交叉路口都至少连接着一条街
道,有的交叉路口可能只连接着一条或两条街道。
小明希望设计一个方案,从编号为 1 的交叉路口出发,每次必须沿街
道去往街道另一端的路口,再从新的路口出发去往下一个路口,直到所有
的街道都经过了正好一次。
输入格式
输入的第一行包含两个整数 n, m,表示交叉路口的数量和街道的数量,
交叉路口从 1 到 n 标号。
接下来 m 行,每行两个整数 a, b,表示和标号为 a 的交叉路口和标号
为 b 的交叉路口之间有一条街道,街道是双向的,小明可以从任意一端走
向另一端。两个路口之间最多有一条街道。
输出格式
如果小明可以经过每条街道正好一次,则输出一行包含 m+1 个整数 p1,
p2, p3, …, pm+1,表示小明经过的路口的顺序,相邻两个整数之间用一个
空格分隔。如果有多种方案满足条件,则输出字典序最小的一种方案,即
首先保证 p1最小,p1最小的前提下再保证 p2最小,依此类推。
如果不存在方案使得小明经过每条街道正好一次,则输出一个整数-1。
样例输入
4 5
1 2
1 3
1 4
2 4
3 4
样例输出
1 2 4 1 3 4
主要考察欧拉路,首先判断能不能形成欧拉路或者欧拉回路,至于什么是欧拉路可以看离散数学or百度,排除完,剩下的就是能形成欧拉路的情况,首先用邻接链表存储图的结构(当然也可以用邻接矩阵。),对链表进行排序或者有序插入均可,因为题目中要输出字典序最小的,最重要的就是输出,靠一个visited_edge的二维矩阵来保证边只被遍历一次(相当于做标记,就好比DFS对节点标记一样。)这是大概地思路。
本人能力有限,难免出错,欢迎大神评论指点,再有,这个代码仅供参考,希望参考者能写出更棒的、更高效的代码,ps:代码还未简化,略糙。
代码如下:
#include<stdio.h>
#include <stdlib.h>
#include<string.h>
typedef struct Node
{
int adj_v;
struct Node *next;
}EdgeNode;
typedef struct
{
int vert;
int size;
EdgeNode *first_edge;
}VertNode;
typedef struct
{
VertNode *adjlink;
int **visited_edge;
int *visited;
int vert_num,edge_num;
}AdjLGraph;
int InsertEdge(AdjLGraph *,int,int);
void InitGraph(AdjLGraph **,int,int);
int DFS(AdjLGraph *);
int Euler(AdjLGraph *);
void PrintPath(AdjLGraph *);
void SortGraph(AdjLGraph *);
void SortAdjLink(EdgeNode *);
int NotDone(AdjLGraph *);
int main()
{
int v,e,v1 = -1,v2 = -1,i;
scanf("%d%d",&v,&e);
AdjLGraph *G;
G = malloc(sizeof(AdjLGraph));
InitGraph(&G,v,e);
for(i =0;i < e;i++)
{
scanf("%d%d",&v1,&v2);
if(!InsertEdge(G,v1,v2))
break;
}