• LC 1489. Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree (tarjan, 最小生成树)


    link

    referenct to @617280219

    1. Sort and group edges by weight. In each step we process one group of edges
    2. Discard the edges whose ends are already connected
    3. Run Tarjan's bridge finding algorithm on each connnected part of the subgraph. Add bridges to critical and the rest to pseudo-critical
    4. Use union-find to connect the edges' two ends.
    class Solution {
    public:
        struct Edge{
            int u;
            int v;
            int id;
        };
        int N;
        int fa[100];
        int cri[200];
        int pcri[200];
        int dict[100];
        int low[100];
        int timer;
        
        int find(int p){
            if(p==fa[p]) return p;
            fa[p]=find(fa[p]);
            return fa[p];
        }
        
        bool uni(int p, int q){
            int proot=find(p);
            int qroot=find(q);
            if(proot==qroot) return false;
            fa[proot]=qroot;
            return true;
        }
        
        void tarjan(int u,  vector<vector<pair<int,int>>> &adj, int parent){
            ++timer;
            dict[u]=low[u]=timer;
            for(auto& p:adj[u]){
                if(p.first==parent) continue;
                if(dict[p.first]!=-1){
                    low[u]=min(low[u],dict[p.first]);
                }else{
                    tarjan(p.first,adj,u);
                    if(dict[u]<low[p.first] && pcri[p.second]!=1){
                        cri[p.second]=1;
                    }
                    low[u]=min(low[u],low[p.first]);
                }
            }
        }
        
        vector<vector<int>> findCriticalAndPseudoCriticalEdges(int n, vector<vector<int>>& edges) {
            int en=edges.size();
            N=n;
            map<int,vector<Edge>> mp;
            for(int i=0;i<en;i++){
                auto &e=edges[i];
                mp[e[2]].push_back(Edge{e[0],e[1],i});
            }
            for(int i=0;i<N;i++) fa[i]=i;
            for(auto& m:mp){
                vector<Edge>& es=m.second;
                unordered_map<int,vector<int>> pathes;
                for(auto& e:es){
                    int ur=find(e.u);
                    int vr=find(e.v);
                    if(ur==vr) continue;
                    if(ur<vr) swap(ur,vr);
                    pathes[ur*N+vr].push_back(e.id);
                }
                vector<vector<pair<int,int>>> adj(N);
                vector<Edge> n_edges;
                for(auto& p:pathes){
                    if(p.second.size()>1){
                        for(int i:p.second) pcri[i]=1;
                    }
                    int ur=p.first/N;
                    int vr=p.first%N;
                    int id=p.second[0];
                    adj[ur].push_back({vr,id});
                    adj[vr].push_back({ur,id});
                    n_edges.push_back(Edge{ur,vr,id});
                    uni(ur,vr);
                }
                memset(dict,-1,sizeof(dict));
                timer=0;
                for(auto& e:n_edges){
                    if(dict[e.u]==-1){
                        tarjan(e.u,adj,-1);
                    }
                }
                for(auto& e:n_edges){
                    if(cri[e.id]==0) pcri[e.id]=1;
                }
            }
            vector<vector<int>> res;
            vector<int> res1,res2;
            for(int i=0;i<en;i++) {
                if(cri[i]) res1.push_back(i);
                else if(pcri[i]) res2.push_back(i);
            }
            res.push_back(res1);
            res.push_back(res2);
            return res;
        }
    };
    
  • 相关阅读:
    《JavaScript高级程序设计》扩展关于动态原型
    “三角边”的那点事儿
    请允许我说:数学是如此美丽!
    球面模型分解及仿flash标签云
    关于Javascript模块化和命名空间管理
    我所了解的关于JavaScript定义类和对象的几种方式
    正因为我们是前端,所以代码更需要优雅
    “作弊”还是创意?伪3D
    mybatis常用jdbcType数据类型以及对应的JavaType
    mdx之计算成员和命名集
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/13201025.html
Copyright © 2020-2023  润新知