本文用纯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;
}
if(i<G->edge_num)
{
printf("Insert error!\n");
return 0;
}
if(DFS(G) != G->vert_num||(Euler(G) != 2&&Euler(G) != 0)||(Euler(G)==2&&G->adjlink[1].size%2==0))
{
printf("-1\n");
return ;
}
SortGraph(G);
PrintPath(G);
return 0;
}
int NotDone(AdjLGraph *G)
{
int i,j,count = 0;
for(i = 1;i<=G->vert_num;i++)
for(j = 1;j<=G->vert_num;j++)
if(G->visited_edge[i][j] == 0)
count++;
//printf("%d\n",count);
return count;
}
void SortAdjLink(EdgeNode *pe)
{
EdgeNode *p,*q,*pre;
p = malloc(sizeof(EdgeNode));
q = malloc(sizeof(EdgeNode));
pre = malloc(sizeof(EdgeNode));
p = q = pre = pe;
if(!p->next)
return;
while(p)
{
q = p->next;
pre = q;
int min = p->adj_v;
while(q)
{
if(q->adj_v < min)
{
min = q->adj_v;
pre = q;
}
q = q->next;
}
if(min!=p->adj_v)
{
int temp = p->adj_v;
p ->adj_v = pre ->adj_v;
pre ->adj_v = temp;
}
p = p->next;
}
}
void SortGraph(AdjLGraph *G)
{
int i ;
for(i = 1;i <= G->vert_num ; i++)
SortAdjLink(G->adjlink[i].first_edge);
}
void PrintPath(AdjLGraph *G)
{
EdgeNode *p = malloc(sizeof(EdgeNode));
printf("1 ");
int j,i=1;
int n = 5;
while(n--)
{
p = G->adjlink[i].first_edge;
for(j = 1;j <= G->adjlink[i].size;j++)
{
if(p&&!G->visited_edge[i][p->adj_v])
{
printf("%d ",p->adj_v);
G->visited_edge[i][p->adj_v] = G->visited_edge[p->adj_v][i] = 1;
break;
}
/*while(G->visited_edge[i][p->adj_v] == 1 && p)
p = p->next;*/
p = p->next;
}
i = p->adj_v;
}
}
int Euler(AdjLGraph *G)
{
int i , count = 0;
for(i = 1;i<= G->vert_num;i++)
if(G->adjlink[i].size % 2 == 1)
count++;
return count;
}
int DFS(AdjLGraph *G)
{
if(G->vert_num == 0)
return -1;
else
{
G->visited[1] = 1;
int i;
EdgeNode *p = malloc(sizeof(EdgeNode));
int count = 1;
for(i = 1;i<=G->vert_num;i++)
{
for(p = G->adjlink[i].first_edge;p;p = p->next)
{
if(G->visited[p->adj_v] == 0)
{
count++;
G->visited[p->adj_v] = 1;
}
}
}
return count;
}
}
void InitGraph(AdjLGraph **G,int v,int e)
{
(*G)->edge_num = e;
(*G)->vert_num = v;
(*G)->adjlink = malloc(sizeof(VertNode)*(v+1));
(*G)->visited = malloc(sizeof(int)*(v+1));
(*G)->visited_edge =(int **) malloc(sizeof(int *)*(v+1));
(*G)->adjlink[0].first_edge = NULL;
int i,j;
for(i = 1;i <= (*G)->vert_num ;i++)
{
(*G)->adjlink[i].first_edge = NULL;
(*G)->adjlink[i].vert = i;
(*G)->adjlink[i].size = 0;
(*G)->visited[i] = 0;
}
for(i = 1;i<v+1;i++)
(*G)->visited_edge[i] = (int *)malloc(sizeof(int)*(v+1));
for(i = 1;i<v+1;i++)
for(j = 1;j<v+1;j++)
(*G)->visited_edge[i][j] = -1;
}
int InsertEdge(AdjLGraph *G,int v1,int v2)
{
int i = 0,j = 0,k;
EdgeNode *s;
for(k = 1;k <= G->vert_num ;k++)
{
if(G->adjlink[k].vert == v1) i = k;
if(G->adjlink[k].vert == v2) j = k;
}
if(!i&&!j)
{
printf("no node\n");
return 0;
}
s = G->adjlink[v1].first_edge;
while(s && s->adj_v != v2)
s = s->next;
if(s)
return 1;
else
{
s = malloc(sizeof(EdgeNode));
s->adj_v = v2;
s->next = G->adjlink[v1].first_edge;
G->adjlink[v1].first_edge = s;
s = malloc(sizeof(EdgeNode));
s->adj_v = v1;
s->next = G->adjlink[v2].first_edge;
G->adjlink[v2].first_edge = s;
G->adjlink[v1].size++;
G->adjlink[v2].size++;
G->visited_edge[v1][v2] = G->visited_edge[v2][v1] = 0;
return 1;
}
}
本题没有在CSP的oj上提交,只是提供一个思路,因为本人在做这道题的时候没有清晰的思路,网上找的大多是c++的代码,因此本文用纯c来写,希望初学C语言的萌新有一个参考。