图算法中的常用代码

并查集模板
主要用于解决关于连通的一些问题

void Initial(){
    for(int i=0;i<MAXN;i++){
        father[i]=i;//根结点指向自己
        height[i]=0;
        //inDegree[i]=0;
        //visit[i]=false;
    }
}

int Find(int x){
    if(father[x]!=x) father[x]=Find(father[x]);//注意写法,路径压缩
    return father[x];
}

void Union(int x,int y){
    x=Find(x);
    y=Find(y);
    if(x!=y){
        if(height[x]<height[y]) father[x]=y;
        else if(height[x]>height[y]) father[y]=x;//前面两种情况树高并没有变
        else{
            father[y]=x;
            height[x]++;
        }
    }
    return ;
}

邻接表

struct Edge{
    int to;
    int length;
    Edge(int t,int l):to{t},length(l){}
};
vector<Edge> graph[MAXN];

最小生成树

int Kruskal(int n,int edgeNumber){
    Initial(n);
    sort(edge,edge+edgeNumber);
    int sum=0;
    for(int i=0;i<edgeNumber;i++){
        Edge current=edge[i];
        //cout<<current.from<<"->"<<current.to<<" "<<current.length<<endl;
        if(Find(current.from)!=Find(current.to)){
            Union(current.from,current.to);
            sum+=current.length;
        }
    }
    return sum;
}

最短路径

struct Point{//结点
    int number;
    int distance;
    Point(int n,int d):number(n),distance(d){}
    bool operator< (const Point& p) const{//重载小于
        return distance>p.distance;
    }
};
int dis[MAXN];

void Dijkstra(int s){
    priority_queue<Point> pqueue;
    dis[s]=0;
    pqueue.push(Point(s,dis[s]));
    while(!pqueue.empty()){
        int u=pqueue.top().number;//离源点最近的点
        pqueue.pop();
        for(int i=0;i<graph[u].size();i++){
            int v=graph[u][i].to;//u为顶点的编号,i为边的序号
            int d=graph[u][i].length;
            if(dis[v]>dis[u]+d){
                dis[v]=dis[u]+d;
                pqueue.push(Point(v,dis[v]));
            }
        }
    }
    return ;
}

拓扑排序

int inDegree[MAXN];
vector<int> TopologicalSort(int n){
    vector<int> topology;
    priority_queue<int,vector<int>,greater<int> > node;//逆向优先队列,为了实现拓扑序列不唯一时编号小的在前面
    for(int i=1;i<=n;i++){//i是从1到n,即结点的编号
        if(inDegree[i]==0){//先把初始入度为零的全部放入队列
            node.push(i);
        }
    }
//求解拓扑序列时一定先把上一层的所有全部入队后再入队下一层,所以优先队列不会干扰
    while(!node.empty()){
        int u=node.top();
        node.pop();
        topology.push_back(u);
        for(int i=0;i<graph[u].size();i++){//遍历当前pop出的结点的所有出弧
            int v=graph[u][i];
            inDegree[v]--;
            if(inDegree[v]==0){//u的所有出弧全部去掉后如果有入度为零的则push进队列
                node.push(v);
            }
        }
    }
    return topology;
}

关键路径
基于拓扑顺序去遍历的

void CriticalPath(int n){
    vector<int> topology;//拓扑序列
    queue<int> node;
    for(int i=0;i<n;i++){
        if(inDegree[i]==0){
            node.push(i);
            earliest[i]=1;//初始化为1,题目中的要求:1ns
        }
    }
    while(!node.empty()){
        int u=node.front();
        topology.push_back(u);
        node.pop();
        for(int i=0;i<graph[u].size();i++){
            int v=graph[u][i].to;
            int l=graph[u][i].length;
            earliest[v]=max(earliest[v],earliest[u]+l);//正向找最大,形成earliest
            inDegree[v]--;
            if(inDegree[v]==0) node.push(v);
        }
    }
    for(int i=topology.size()-1;i>=0;i--){
        int u=topology[i];
        if(graph[u].size()==0) latest[u]=earliest[u];//汇点的最晚开始时间初始化
        else latest[u]=INF;//非汇点的最晚开始时间的初始化
        for(int j=0;j<graph[u].size();j++){
            int v=graph[u][j].to;
            int l=graph[u][j].length;
            latest[u]=min(latest[u],latest[v]-l);//逆向找最小,形成latest
        }
    }
}
发布了23 篇原创文章 · 获赞 21 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_38440882/article/details/104363918