功能描述
同时用邻接矩阵与邻接表描述图的存储结构，读取n,m,dir和m条边，构建两种表示并打印结果。
支持无向和有向图：dir=0无向，dir=1有向。
数据结构
邻接矩阵：GraphMat { int n; int directed; int **mat; }，mat[i][j]为0/1（是否存在边）。
邻接表：GraphList { int n; int directed; Edge **head; }，Edge { int to; Edge* next;}。
辅助函数
创建矩阵：GraphMatCreate(int n, int directed)分配n×n二维数组并清零。
加边到矩阵：GraphMatAddEdge写mat[u-1][v-1]=1，无向图对称写入。
释放矩阵：GraphMatFree逐行释放再释放行指针数组。
创建邻接表：GraphListCreate分配头指针数组。
加边到邻接表：GraphListAddEdge头插法建立链表；无向图对称插入。
释放邻接表：GraphListFree逐链释放每个顶点的边链。
打印矩阵：PrintMatrix行输出。
打印邻接表：PrintList每顶点输出邻居列表。
核心算法
邻接矩阵初始化与加边：O(n²)清零，边更新为O(1)。
邻接表插入：每条边O(1)头插。
初始化与交互
Windows控制台设置为UTF-8，避免中文乱码。
读取n,m,dir，随后读取m条边并同时写入两种结构。
打印两种表示并释放内存。
输入与输出
输入：第一行n m dir；接下来m行每行u v。
输出：先打印邻接矩阵（0/1），再打印邻接表的每个顶点的邻居列表。
代码特点
二维数组int**行指针+行内存独立分配；可读性好，访问用mat[i][j]。
邻接表使用链式前插，简单高效。
函数分层清晰，构建、打印与释放职责分明。
边界与异常处理
输入校验：n>0，m≥0，dir∈{0,1}，边索引必须在[1..n]。
内存管理：分配失败未显式处理，但所有已分配资源均在退出前释放。
时间与空间复杂度
邻接矩阵：初始化O(n²)，加边O(m)，打印O(n²)；空间O(n²)。
邻接表：创建O(n)，加边O(m)，打印O(n+m)；空间O(n+m)。
可能扩展
邻接矩阵采用单块连续内存并行指针映射，提升局部性。
支持权值图（矩阵存权、表结点包含权）。
输入格式扩展支持 0 基顶点编号与批量文件读取。

exercise/44.c 实验分析

功能描述
读取有向图n、m以及m条边x,y,z（正权），用邻接矩阵存储并运行Dijkstra，计算1号点到n号点的最短距离；程序按人机交互提示读入并以中文提示输出结果。
数据结构
图结构：AMGraphStruct { int vexnum; int **arcs; }，以int**邻接矩阵存储；AMGraph为指针别名。
辅助数组：S[]标记已确定最短路的顶点；D[]为源点到各顶点的当前最短距离；Path[]记录前驱。
常量：MaxInt为不可达哨值，MAXN为数组容量上限。
辅助函数
ShortestPath_DIJ(AMGraph G, int v0)：初始化S、D、Path；每轮从未确定集合中选取当前距离最小顶点v，加入S并对其所有邻接点w进行松弛更新。
核心算法
Dijkstra（邻接矩阵实现）：每轮选择最小未访问顶点并进行全邻接松弛，复杂度O(n²)。
初始化与交互
Windows控制台设置为UTF-8；提示输入n、m与每条边x、y、z；运行后以中文提示输出从源点（内部索引0）到目标点（内部索引n-1）的最短距离或不可达信息。
输入与输出
输入：第一行n m；其后m行x y z，顶点编号为1基，边权均为正值。
输出：若可达，输出“从顶点0到顶点n-1的最短路径长度为：D[n-1]”；不可达，输出“从顶点0到顶点n-1不存在路径”。
代码特点
使用指针形式的邻接矩阵，初始化对角为0、其余为MaxInt；重边保留较小权值以确保Dijkstra正确性；全局辅助数组简化函数签名。
边界与异常处理
基本输入失败时直接返回；未显式校验n与边权范围；不可达场景需要在选点阶段考虑无候选的情况以避免未赋值索引的使用（建议在未选出顶点时终止循环）。
时间与空间复杂度
时间：O(n²) 选择与松弛；空间：邻接矩阵O(n²)，辅助数组O(n)。
可能扩展
改为邻接表+最小堆实现，将复杂度优化为O(m log n)；统一输出为OJ格式仅输出数值或-1；增加输入范围校验与路径重建输出。