前向星是一种特殊的边集数组。
不同于邻接表和邻接矩阵对顶点的处理,前向星存图处理的是边与边的关系。
int cnt; //记录边的编号 int head[maxn]; //head[u]表示上一个以u为起点的边的编号,初始化-1 struct st //储存边的信息 { int to; //边的终点 int w; //边的权值 int next; //下一个同起点边的编号 } edge[maxn];
这里再解释一下head数组和edge数组:
edge[i]并不是表示第i个顶点,而是编号为i的边,edge结构体不包含边的起点,但包含了与该边同起点的边的编号。
head[u]记录最后一条以u为起点的边的编号;
若head[u]==-1,则说明没有以u为起点的边;
若head[u]!=1,则可以找到最后一条边的编号v,经由edge[v].next找到下一条边,直到next==-1。
inline void add(int u,int v,int w) //加边 { edge[++cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt; } void dfs(int u,int pre) { for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==pre) continue; dfs(v,u); } }
以下是【每日一题】 Shortest Path 的ac代码:
题目:https://ac.nowcoder.com/acm/problem/13886
#include <iostream> #include <queue> #include <set> #include <map> #include <vector> #include <stack> #include <cmath> #include <algorithm> #include <cstdio> #include <cctype> #include <functional> #include <string> #include <cstring> #include <sstream> #include <deque> using namespace std; typedef long long ll; typedef pair<int,int> P; typedef pair<int,P> Q; const int inf1=2e9+9; const ll inf2=8e18+9; const ll mol=998244353; const int maxn=2e4+9; const int maxx=1e9+9; int n; ll ans; int cnt,head[maxn]; struct st{int to,w,next;} edge[maxn]; inline void add(int u,int v,int w) { edge[++cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt; } int dfs(int u,int pre) { int cnt_=1; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==pre) continue; if(dfs(v,u)) { cnt_++; ans+=edge[i].w; } } return cnt_%2; } int main() { int t; scanf("%d",&t); while(t--) { cnt=0; memset(head,-1,sizeof head); scanf("%d",&n); for(int i=0;i<n-1;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } ans=0; dfs(1,0); printf("%lld\n",ans); } }
当中要注意的是,对于无向边,每条边要储存两次,所以head和edge都要开原来的原来的两倍大小。