链式前向星
参考资料:
[1]:https://blog.csdn.net/acdreamers/article/details/16902023
[2]:https://blog.csdn.net/ZHangFFYY/article/details/77871897
如果用链式前向星,就可以避免排序.
1 const int maxn=1e3+50; 2 3 int head[maxn];//head[i] : 表示以i为起点的第一条边存储的位置,初始化为-1 4 int num;//num:表示当前边在链式前向星中的编号,初始化为 0 5 struct Edge//边的结构体 6 { 7 int to;//G[i].to:表示第i条边的终点 8 int w;//G[i].w为边权值 9 int next;//G[i].next表示与第i条边同起点的下一条边的存储位置 10 }G[2*maxn];//无向图需要2倍 11 //实际上你会发现这里的第一条边存储的位置其实就是以i为起点的所有边的最后输入的那个编号。 12 void addEdge(int u,int v,int w)//加边操作 13 { 14 G[num].to=v; 15 G[num].w=w; 16 G[num].next=head[u]; 17 head[u]=num++; 18 } 19 void Prine(int u)//输出与u相关的边 20 { 21 //~ : 按位取反,只有 ~(-1) == 0,这就是为什么初始化 head[]为-1的原因 22 for(int i=head[u];~i;i=edge[i].next) 23 { 24 int v=edge[i].to; 25 int w=edge[i].w; 26 cout<<u<<"->"<<v<<' '<<w<<endl; 27 } 28 } 29 void Init()//初始化操作 30 { 31 memset(head,-1,sizeof(head)); 32 num=0; 33 }
现在我们还是按照上面的图和输入来模拟一下:
G[0].to = 2; G[0].next = -1; head[1] = 0;
G[1].to = 3; G[1].next = -1; head[2] = 1;
G[2].to = 4; G[2],next = -1; head[3] = 2;
G[3].to = 3; G[3].next = 0; head[1] = 3;
G[4].to = 1; G[4].next = -1; head[4] = 4;
G[5].to = 5; G[5].next = 3; head[1] = 5;
G[6].to = 5; G[6].next = 4; head[4] = 6;
很明显,head[i]保存的是以i为起点的所有边中编号最大的那个,而把这个当作顶点i的第一条起始边的位置.
这样在遍历时是倒着遍历的,也就是说与输入顺序是相反的,不过这样不影响结果的正确性.
我们在遍历以u节点为起始位置的所有边的时候是这样的:
for(int i=head[u]; ~i ;i=G[i].next)//~按位取反,只有当i==-1时,~i才为0,这就是为什么初始化head[]为-1的原因,或将~i改为i != -1