Skip to content

图的存储

约 340 个字 98 行代码 预计阅读时间 3 分钟

邻接矩阵

二维数组w[u][v]存储从u到v的边的权值
* 时间复杂度\(O(n^2)\)
* 空间复杂度\(O(n^2)\)
适合在点数不多的稠密图上使用

边集数组

边集数组e[i]存储第i条边的{起点u,终点v,边权w},常用结构体
* 时间复杂度\(O(mn)\)
* 空间复杂度\(O(m)\)

C++
struct edge{
int u,v,w;
};
vis[N];
void dfs(int u){
    vis[u]=true;
    for(int i=1;i<=m;i++){
        if(e[i].u==u){
            int v=e[i].v,w=e[i].w;
            printf("%d,%d,%d",u,v,w);
            if(vis[v]) continue;
            dfs(e[i].v);
        }
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
    cin>>a>>b>>c;
    e[i]={a,b,c};
    }
    dfs(1);
}

邻接表

出边数组e[u][i]存储u点的所有出边{终点v和边权w}
* 时间复杂度\(O(n+m)\)
* 空间复杂度\(O(n+m)\)
各种图,不能处理反向边

C++
struct edge{int v,w;};
vector<edge> e[N];边集

void dfs(int u,int fa){
    for(auto ed:e[u]){
        int v=ed.v,w=ed.w;
        if(v==fa)continue;
        printf("%d%d%d",u,v,w);
        dfs(v,u);
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>a>>b>>c;
        e[a].push_back({b,c});
        e[b].push_back({a,c});
    }
    dfs(1,0);//从哪个点以及它的父节点,这里是对于树的深搜
    return 0;
}

链式邻接表

边集数组e[i]存储第j条边的{起点u,终点v,边权w}
表头数组h[u][i]存储u点的所有出边的编号
* 时间复杂度\(O(n+m)\)
* 空间复杂度\(O(n+m)\)
应用于各种图,能处理反向边

C++
struct edge{int u,v,w};
vector<edge> e;
vector<int> h[N];
void add(int a,int b,int c){
    e.push_back({a,b,c});
    h[a].push_back(e.size()-1);//起始下标是0
}
void dfs(int u,int fa){
    for(int i=0;i<h[u].size();i++){
    int j=h[u][i];
    int v=e[j].v,w=e[j].w;
    if(v==fa)continue;
    printf("%d%d%d",u,v,w);
    dfs(v,u);
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a>>b>>c;
        add(a,b,c);
        add(b,a,c);
    }
    dfs(1,0);//也是树的深搜
    return 0;
}

常用在网络流中

链式前向星

一个表头数组悬挂多个链表
边集数组e[i]存储第i条出边的{终点v,边权w,下一条出边ne}
表头数组h[u]存储u点的第一条出边的编号
边的编号idx取0,1,2,3...
* 时间复杂度\(O(n+m)\)
* 空间复杂度\(O(n+m)\)

C++
struct edge{int v,w,ne;};
edge e[M];
int idx,h[N];
void add(int a,int b,int c){
    e[idx]={b,c,h[a]};//第一次h[a]肯定是-1,表示这是尾巴的边,后面的边都是插在前面的
    h[a]=idx;//意味着idx编号的这条边是a目前的第一条出边
    idx++;//接下来考虑下一条边
}
void dfs(int u,int fa){
    for(int i=h[u];~i;i=e[i].ne){
        int v=e[i].v,w=e[i].w;
        if(v==fa) continue;
        printf("%d%d%d",u,v,w);
        dfs(v,u);
    }
}
int main(){
    cin>>n>>m;
    memset(h,-1,sizeof(h));
    for(int i=1;i<=m;i++){
        cin>>a>>b>>c;
        add(a,b,c);
        add(b,a,c);
    }
    dfs(1,0);
    return 0;
}