Contents
- 1 So for the following picture
- 2 The order in which we enter the edges is
- 3 Then after sorting, you will get
- 4 get
- 5 We establish the edge structure as
- 6 The add function for adding edges is like this
- 7 Add duplicate edges
- 8 Now let’s simulate it according to the above picture and input.
- 9 This is what happens when traversing all the edges starting from node u
- 10 Complete sample
Forward star is a special edge set array. We sort each edge in the edge set array according to the starting point from small to large. If the starting points are the same, we sort each edge according to the end point from small to large.
And record the starting position and storage length of all edges starting from a certain point in the array, then the forward star is constructed.
Use $len[i]$ to record the storage length of all edges starting from i in the array.
Use $head[i]$ to record the first storage location in the array with i as the edge set.
So for the following picture
The order in which we enter the edges is
1 2
2 3
3 4
1 3
4 1
1 5
4 5
Then after sorting, you will get
编号: 1 2 3 4 5 6 7
起点u: 1 1 1 2 3 4 4
终点v: 2 3 5 3 4 1 5
get
head[1] = 1 len[1] = 3
head[2] = 4 len[2] = 1
head[3] = 5 len[3] = 1
head[4] = 6 len[4] = 2
However, there will be a sorting operation using forward star. If quick sorting is used, the time will be at least $\Omicron(n \log n)$
If you use chained forward stars, you can avoid sorting.
We establish the edge structure as
struct Edge {
int next;
int to;
int w;
};
Where $edge[i].to$ represents the end point of the $i$-th edge, $edge[i].next$ represents the storage location of the next edge with the same starting point as the i-th edge, $edge[i].w $ is the edge weight.
There is also an array $head$, which is used to represent the storage position of the first edge starting from $i$. In fact, you will find that the storage position of the first edge here is actually
The number entered at the end of all edges starting from $i$.
The $head$ array is generally initialized to $-1$
The add function for adding edges is like this
void add(int u,int v,int w) {
edge[cnt].w = w;
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
Initialize $cnt = 0$
Add duplicate edges
void add_edge(int u, int v, int w) {
for(int i = head[u]; ~i; i = edge[i].nxt) {
if(edge[i].v == v) {
if(edge[i].w > w)
edge[i].w = w;
return;
}
}
tot++;
edge[tot].u = u;
edge[tot].v = v;
edge[tot].w = w;
edge[tot].nxt = head[u];
head[u] = tot;
}
Now let’s simulate it according to the above picture and input.
edge[0].to = 2; edge[0].next = -1; head[1] = 0;
edge[1].to = 3; edge[1].next = -1; head[2] = 1;
edge[2].to = 4; edge[2],next = -1; head[3] = 2;
edge[3].to = 3; edge[3].next = 0; head[1] = 3;
edge[4].to = 1; edge[4].next = -1; head[4] = 4;
edge[5].to = 5; edge[5].next = 3; head[1] = 5;
edge[6].to = 5; edge[6].next = 4; head[4] = 6;
Obviously, $head[i]$ saves the highest number among all the edges starting from $i$, and regards this as the position of the first starting edge of vertex $i$.
In this way, the traversal is performed backwards, which means that the input order is reversed, but this does not affect the correctness of the results.
For example, in the above figure, there are $1$ edges starting from node $3$, and their numbers are $0,3,5, 1, 5$ respectively, and $head[XNUMX] = XNUMX$
This is what happens when traversing all the edges starting from node u
for(int i=head[u];~i;i=edge[i].next)
That is to say, first traverse the edge numbered $5$, which is $head[1]$, then $edge[5].next$, which is the edge numbered $3$, and then continue $edge[3].next$ , that is, the edge numbered $0$, which can be seen to be in reverse order.
Complete sample
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 1e6; //点数
const int MAXM = 1e7; //边数
struct E { //存边结构体
int u;
int v;
int w;
int nxt; //下一条边在edge中的下标
} edge[MAXM];
bool vis[MAXN];
int head[MAXN]; //以节点i开头的边在edge中的开头下标
int tot = 0; //edge中的边数
void init() { //初始化
memset(head, -1, sizeof head);//-1表示改点无出度
memset(vis, false, sizeof vis);
}
//加边函数
void add_edge(int u, int v, int w) {
tot++;
edge[tot].u = u;
edge[tot].v = v;
edge[tot].w = w;
edge[tot].nxt = head[u];
head[u] = tot;
}
//实例
void dfs(int root) {
vis[root] = true;
printf("%d\n", root);
for(int i = head[root]; ~i; i = edge[i].nxt)
if(!vis[edge[i].v])
dfs(edge[i].v);
}
int main() {
init();
int m;
scanf("%d", &m);
while(m--) {
int u, v;
scanf("%d %d", &u, &v);
add_edge(u, v, 0);
}
dfs(1);
return 0;
}