图的存储方式
昨天 听caicai讲了几种关于图的存储方式 又学了好多 家有caicai 如有一宝 -> 转自 晓爷
下面 我所讲的 都是基于 有向图的建图方式
i:
map[a][b] ---最基础的邻接矩阵 直接用二维数组
ii:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 struct graph 2 { 3 int num; // ---指向 下一个顶点 ( 表示当前已经与 该顶点相邻的个数 ) 4 int next[x]; // -- 与 该顶点 第( x+1 )个相邻的点的标号 5 int dist[x]; // -- 与 该顶点 第 ( x+1 )个相邻的点与该点之间的距离 --通过它来进行松弛操作 6 7 }mp[y] 8 bool vis[y] // -- 各个顶点 是否已经被访问过 在某个状态中 如 在spfa中 表示 是否已经入队 9 int dist[y] // -- 源点 -> 各个顶点的距离 10 // -- 这里的 next 和 dist 数组 是相对应的 所以 数组大小声明为相同 11 int main() 12 { 13 int temp; 14 scanf( "%d %d %d" , &from , &to , &dist ); 15 temp = mp[from].num; 16 mp[from].next[temp] = to; 17 mp[from].dist[temp] = dist; 18 mp[from].num++; 19 // temp++ 这是 错的 千万不要犯这种错误 20 } 21 22 // 或者 可以用下面 这种方式 代码更加简洁 但可读性没有上面的好 23 mp[from].next[ mp[from].num ] = to; 24 mp[from].dist[ mp[from].num++ ] = dist;
iii:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // y -- 顶点个数 2 // x -- 与 该顶点 相邻的顶点个数 3 4 struct graph 5 { 6 int num; // ---指向 下一个顶点 ( 表示当前已经与 该顶点相邻的个数 ) 7 int next[x]; // -- 与 该顶点 第( x+1 )个相邻的点的标号 8 int dist[x]; // -- 与 该顶点 第 ( x+1 )个相邻的点与该点之间的距离 --通过它来进行松弛操作 9 10 }mp[y] 11 bool vis[y] // -- 各个顶点 是否已经被访问过 在某个状态中 如 在spfa中 表示 是否已经入队 12 int dist[y] // -- 源点 -> 各个顶点的距离 13 // -- 这里的 next 和 dist 数组 是相对应的 所以 数组大小声明为相同 14 15 iii: 16 17 // num --- 边的总数 每有一条边的加入 就+1 18 // x --- 顶点的个数 19 struct garph 20 { 21 int to; // 当结构体标号为num时 相邻的边的顶点 22 int dist; // 当结构体标号为num时 相邻的边的距离 23 int next; // 当结构体标号为num时 记录这条边的出发点的前面出现过的结构体标号,就是一个向前查询 类似于一个索引 很高效 通过是否为-1 来判断循环终止 24 }edge[x*3]; // 边的条数 25 26 int head[x]; // 指向有着相同源点的顶点的标号 head的下标 即当前边的顶点的下标 27 28 void addedge( int from , int to , int dist ) 29 { 30 edge[num].to = to; //传递 相邻边的顶点 31 edge[num].dist = dist; //传递 距离 32 edge[num].next = head[from]; //通过head数组 来查询在前面的输入中 是否已经出现过相同的源点 如果有 就在此处指向它 方便后面的for遍历查询 33 head[from] = num; //使顶点标号为from的结点 指向 该结构体标号 34 num++; 35 } 36 37 int main() 38 { 39 memset( head , -1 , sizeof(head) ); // 因为我是从0~n 给顶点标号 那么 -1 是代表无前驱指向 当然 如果是从 1~n的 我当然可以初始化为0 40 scanf( "%d %d %d" , &from , &to , &dist ) 41 addedge( from , to , dist ); 42 for( int i = head[now] ; i!=-1 ; i = edge[i].next )//实现方式 43 }
iV:
上述的存储方式 都是放在二维数组 或者 结构体中 不具备灵活性 我们可以将它放在 容器 vector中 当然 这样可以节省内存 同时我们也要也牺牲时间的代价来获得 用何种方式 还得看具体 情况
通过vector<class>vec[num] 来操作
class---> 基本数据类型 或 自定义数据类型
这里 还有一篇 讲的比我更为透彻 超神 -> click it
如果 有任何不对的地方 请给我指出来 为了不误导后面的无意看到此文的人
just follow your heart