CSP送货问题C语言版---For初学者

本文用纯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语言的萌新有一个参考。

猜你喜欢

转载自blog.csdn.net/a_52hz/article/details/85721199