|
|
楼主 |
发表于 2013-6-30 00:09:44
|
显示全部楼层
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 调试开关
#define _DEBUG_ 0
// 最大顶点个数
#define MAX_VERTEX 32
// 取最大值
#define MAX(a, b) ((a) > (b) ? (a) : (b))
// 检测分配内存是否成功
#define CHECK_MALLOC(p)               \
{                                     \
    if (NULL == p)                    \
    {                                 \
        printf("malloc error.\n");    \
        return -1;                    \
    }                                 \
}
// 邻接点结构定义
typedef struct EdgeNode
{
    int adjVex;              // 邻接点在顶点表中的下标
    int weight;              // 权值,这里指距离
    
    struct EdgeNode *next;   // 下一个邻接点
}EdgeNode;
// 顶点表结点定义
typedef struct
{
    int index;               // 城市编号
    EdgeNode *firstEdge;     // 第一个邻接点
}AdjList[MAX_VERTEX];
// 邻接表结构定义
typedef struct
{
    int vertexNum;            // 顶点数
    int edgeNum;              // 边数
    AdjList adjList;          // 邻接表
}GraphAdjList;
// -------------------------------------------------------------------------
// - 函 数 名: initAdjList
// - 功能描述: 初始化邻接表
// - 输入参数: vertexNum:顶点个数;edgeNum:边数
// - 输出参数: graph:邻接图
// - 返 回 值: void
// - 备    注:
// -------------------------------------------------------------------------
void initAdjList(GraphAdjList *graph, int vertexNum, int edgeNum)
{
    int i;
    
    memset(graph, 0, sizeof(GraphAdjList));
    
    graph->vertexNum = vertexNum;
    graph->edgeNum = edgeNum;
    
    for (i = 0; i < graph->vertexNum; i++)
    {
        graph->adjList.index = i;
        graph->adjList.firstEdge = NULL;
    }
}
// -------------------------------------------------------------------------
// - 函 数 名: createAdjList
// - 功能描述: 创建邻接表
// - 输入参数: 无
// - 输出参数: graph:邻接图
// - 返 回 值: 0:成功;其他:失败
// - 备    注:
// -------------------------------------------------------------------------
int createAdjList(GraphAdjList *graph)
{
    int i;                          // 循环变量
    int from;                       // 起始城市编号
    int to;                         // 目标城市编号
    int distance;                   // 两城市间距离
    EdgeNode *pEdgeNode = NULL;
    
    for (i = 0; i < graph->edgeNum; i++)
    {
        // 从标准输入获取高速公路信息
        fflush(stdin);
        scanf("%d %d %d", &from, &to, &distance);
        // 将高速公路信息加入邻接表
        pEdgeNode = (EdgeNode*)malloc(sizeof(EdgeNode));
        CHECK_MALLOC(pEdgeNode);
        pEdgeNode->adjVex = to - 1;
        pEdgeNode->weight = distance;
        pEdgeNode->next = graph->adjList[from-1].firstEdge;
        graph->adjList[from-1].firstEdge = pEdgeNode;
        
        pEdgeNode = (EdgeNode*)malloc(sizeof(EdgeNode));
        CHECK_MALLOC(pEdgeNode);
        pEdgeNode->adjVex = from - 1;
        pEdgeNode->weight = distance;
        pEdgeNode->next = graph->adjList[to-1].firstEdge;
        graph->adjList[to-1].firstEdge = pEdgeNode;
    }
    
    return 0;
}
#if _DEBUG_
// -------------------------------------------------------------------------
// - 函 数 名: printGraphAdjList
// - 功能描述: 打印邻接表
// - 输入参数: graph:邻接表指针
// - 输出参数: 无
// - 返 回 值: void
// - 备    注: 调试使用,格式为:"[城市编号]: ->(相邻城市编号,距离)"
// -------------------------------------------------------------------------
void printGraphAdjList(const GraphAdjList *graph)
{
    int i;
    EdgeNode *pEdgeNode = NULL;
    
    puts("=========================");
    for (i = 0; i < graph->vertexNum; i++)
    {
        printf("[%d]: ", graph->adjList.index);
        
        pEdgeNode = graph->adjList.firstEdge;
        while (NULL != pEdgeNode)
        {
            printf("->(%d,%d)", pEdgeNode->adjVex + 1, pEdgeNode->weight + 1);
            pEdgeNode = pEdgeNode->next;
        }
        
        printf("\n");
    }
    puts("=========================");
}
#endif
// -------------------------------------------------------------------------
// - 函 数 名: dfs
// - 功能描述: 深度优先遍历邻接图
// - 输入参数: graph:邻接图指针;vertex1:起始城市编号;vertex2:目标城市编号
// - 输出参数: distance:两城市之间距离;visit:访问标记
// - 返 回 值: 0:成功;1:失败
// - 备    注:
// -------------------------------------------------------------------------
int dfs(GraphAdjList *graph, int vertex1, int vertex2, int *distance, int visit[])
{
    EdgeNode *pEdgeNode = NULL;
    // 之前已经访问过,回退
    if (0 != visit[vertex1])
    {
        return 1;
    }
    // 打访问标记
    visit[vertex1] = 1;
    // 找到目标城市,返回成功
    if (graph->adjList[vertex1].index == vertex2)
    {
        return 0;
    }
    // 遍历当前城市的所有邻接城市
    pEdgeNode = graph->adjList[vertex1].firstEdge;
    while (NULL != pEdgeNode)
    {
        // 没访问过则访问
        if (0 == visit[pEdgeNode->adjVex])
        {
            // 加上与当前城市之间的距离
            *distance += pEdgeNode->weight;
            // 递归访问城市
            if (0 == dfs(graph, pEdgeNode->adjVex, vertex2, distance, visit))
            {
                return 0;
            }
        }
        pEdgeNode = pEdgeNode->next;
    }
    // 在当前城市的所有邻接城市中均未找到目标城市,减去距离,回退
    *distance -= graph->adjList[vertex1].firstEdge->weight;
    return 1;
}
// -------------------------------------------------------------------------
// - 函 数 名: getDistance
// - 功能描述: 获取两城市之间的距离
// - 输入参数: graph:邻接图;vertex1:城市1下标;vertex2:城市2下标
// - 输出参数: 无
// - 返 回 值: int 两城市之间的距离
// - 备    注:
// -------------------------------------------------------------------------
int getDistance(GraphAdjList *graph, int vertex1, int vertex2)
{
    int distance = 0;                 // 城市距离
    int visited[MAX_VERTEX] = {0};    // 访问标记
    (void)dfs(graph, vertex1, vertex2, &distance, visited);
    return distance;
}
// -------------------------------------------------------------------------
// - 函 数 名: getMaxDistance
// - 功能描述: 获取图中最远的两座城市之间的距离
// - 输入参数: graph:邻接图
// - 输出参数: 无
// - 返 回 值: int 最大距离
// - 备    注:
// -------------------------------------------------------------------------
int getMaxDistance(GraphAdjList *graph)
{
    int maxDistance = 0;
    int tmpDistance;
    int i, j;
    // 计算各对城市之间的距离,取最大值
    for (i = 0; i < graph->vertexNum; i++)
    {
        for (j = i + 1; j < graph->vertexNum; j++)
        {
            tmpDistance = getDistance(graph, i, j);
#if _DEBUG_
            printf("(%d,%d): %d\n", i + 1, j + 1, tmpDistance);
#endif
            maxDistance = MAX(tmpDistance, maxDistance);
        }
    }
    return maxDistance;
}
// -------------------------------------------------------------------------
// - 函 数 名: calcFee
// - 功能描述: 根据距离计算路费
// - 输入参数: distance:距离
// - 输出参数: 无
// - 返 回 值: int:路费
// - 备    注:
// -------------------------------------------------------------------------
int calcFee(int distance)
{
    return (10 * distance + distance * (distance + 1) / 2);
}
int main()
{
    int cityNum;               // 城市数
    int maxDistance = 0;       // 城市间最大距离
    GraphAdjList graph;        // 邻接图
    scanf("%d", &cityNum);
    
    // 初始化邻接表
    initAdjList(&graph, cityNum, cityNum - 1);
    
    // 建立边表
    if (0 != createAdjList(&graph))
    {
        printf("create graph failed.\n");
        return -1;
    }
#if _DEBUG_
    // 打印邻接表
    printGraphAdjList(&graph);
#endif
    // 遍历邻接表寻找最远的两座城市
    maxDistance = getMaxDistance(&graph);
    // 计算并打印最多的路费
    printf("%d\n", calcFee(maxDistance));
    
    return 0;
}
|
|