搜索与图论

树与图的存储

  1. 邻接矩阵:g[a][b]存储边a→b
  2. 邻接表:对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头节点
int h[N],e[N],idx,ne[N];

//添加一条边a->b
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

//初始化
idx=0;
memset(h,-1,sizeof h);
模板

 

树与图的遍历

  • //时间复杂度 O(n+m), n 表示点数,m 表示边数
  1. dfs  AcWing 846. 树的重心
    int dfs(int u){
        st[u]=true;
        
        for(int i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(!st[j])dfs(j);
        }
    }
    模板



  2. bfs AcWing 847. 图中点的层次
    int bfs(){
        queue<int> q;
        st[1]=true;
        q.push(1);
        
        while(!q.empty()){
            int t=q.front();
            q.pop();
            
            for(int i=h[t];i!=-1;i=ne[i]){
                int j=e[i];
                if(!st[j]){
                    st[j]=true;
                    q.push(j);
                }
            }
        }
    }
    View Code

     

 

拓扑排序

  • 时间复杂度 O(n+m), n 表示点数,m 表示边数
bool topsort(){
    int hh=0,tt=-1;
    for(int i=1;i<=n;++i)if(!d[i])q[++tt]=i;

    while(hh<=tt){
        int t=q[hh++];

        for(int i=h[t];i!=-1;i=ne[i]){
            int j=e[i];
            if(--d[j]==0)q[++tt]=i;
        }

    }
    // 如果所有点都入队了,说明存在拓扑序列;否则不存在拓扑序列。
    return tt==n-1;
}
模板

 

        

kruscal算法

#include<iostream>
using namespace std;

int n,m;// n是点数,m是边数
int p[N];// 并查集的父节点数组

struct Edge{// 存储边
    int a,b,w;
    bool operator<(const Edge &W)const{
        return w<W.w;
    }
}edges[M];

int find(int x){//并查集核心操作
    if(p[x]!=x){
        p[x]=find(p[x]);
    }
    return p[x];
}

int kruscal(){
    sort(edges,edges+m);
    for(int i=1;i<=n;++i)p[i]=i;

    int res=0,cnt=0;//cnt记录连通的边数

    for(int i=0;i<m;++i){
        int a=edges[i].a,b=edges[i].b,w=edges[i].w;

        a=find(a),b=find(b);
        if(a!=b){ // 如果两个连通块不连通,则将这两个连通块合并
            p[a]=b;
            res+=w;
            cnt++;
        }
    }

    if(cnt<n-1)return INF;
    return res;
}
模板

 

朴素Prim算法

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,M=2e5+5,INF=0x3f3f3f3f;

int n;// n表示点数
int g[N][N];// 邻接矩阵,存储所有边
int dis[N];// 存储其他点到当前最小生成树的距离
bool st[N];// 存储每个点是否已经在生成树中

// 如果图不连通,则返回INF(值是0x3f3f3f3f), 否则返回最小生成树的树边权重之和
int prim(){
    memset(dis,0x3f,sizeof dis);
    
    int res=0;
    for(int i=0;i<n;++i){
        int t=-1;
        for(int j=1;j<=n;++j){
            if(t==-1||dis[j]<dis[t])t=j;
        }
        
        if(i&&dis[t]==INF)return INF;
        
        if(i)res+=dis[t];
        st[t]=true;
        
        for(int j=1;j<=n;++j)dis[j]=min(dis[j],g[t][j]);
        
    }
    return res;
    
}
模板

 

posted @ 2023-02-06 00:15  bible_w  阅读(10)  评论(0编辑  收藏  举报