图论基础学习指南

图的存储方式

邻接矩阵

w[u][v]存储从点u到点v的边的权值。

时间复杂度:

空间复杂度:

应用:只在点数不多的稠密图,(n=103,m=106)上使用。

const int N=1010;
int g[N][N];
int vis[N];
int n,m;
int u,v,w;
void dfs(int u){
    vis[u]=true;
    for(int v=1;v<=n;v++){
        if(g[u][v]){
            // pass;
        if(vis[v]) continue;
        dfs(v);
        }
    }
}
int main() {
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>u>>v>>w;
        w[u][v]=w;
        // w[v][u]=w;
    }
     dfs(1);
    return 0;
}

边集数组

边集数组e[i]存储第i条边的{起点u,终点v,边权w}

时间复杂度:

空间复杂度:

应用:在Kruskal算法中,需要将边按边权排序的,直接存边。

const int N=1010,M=1010;
int n,m,a,b,c;
struct edge{
  int u,v,w;
}e[M];//边集 
int 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\n",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};
    // e[i]={b,a,c};
  }
  dfs(1);
  return 0;
}

邻接表

出边数组e[u][i]存储u点的所有出边d{终点v,边权w}

时间复杂度:

空间复杂度:

应用:各种图,不能处理反向边。

const int N=510;
int n,m,a,b,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\n",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;
}

链式邻接表

const int N=510;
int n,m,a,b,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);
}
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\n",u,v,w);
    dfs(v,u);
  }
}
int main(){
  cin>>n>>m;
  for(int i=1;i<=m;i++){
    cin>>a>>b>>c,
    add(a,b,c);
    add(b,a,c);
  }  
  dfs(1, 0);
  return 0;
}

链式前向星

这两条边可以通过互为反向边,可以通过与1的异或运算得到其反向边,01=1,11=0。也就是说如果一条边的下标为i,则其反向边为i^1(需要从0编号开始建图)。这个特性应用在网络流中非常方便。

链式前向星的空间复杂度是O(n)

【结构体写法】

const int N=510,M=3000;
int n,m,a,b,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]=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\n",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;
}

【数组写法】

const int N=2e5+10;
int h[N],e[N],ne[N],idx=0;
void add(int u,int v){
    e[++idx]=v;
    ne[idx]=h[u];
    h[u]=idx;
}
void dfs(int x,int fa){
    for(int i=h[x];i;i=ne[x]){
        if(e[i]!=fa) dfs(e[i],x);
    }
}
posted @ 2023-10-16 20:39  White_Sheep  阅读(2)  评论(0编辑  收藏  举报