zoukankan      html  css  js  c++  java
  • 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;
        }
    };
    
  • 相关阅读:
    poj 2112
    写给学大计python的同学的查错方法
    [Win32 API学习] Edit,ListBox的用法,字体的设置
    [Win32 API] FindFirstFile()和FindNextFile()
    初探C++ win32 api——Hello world!
    [学习笔记]舞蹈链(DLX)(C++指针版)
    2020科大回归记
    SCOI2019AFO记
    [学习笔记]动态动态规划/动态DP/DDP
    BZOJ5343[CTSC2018]混合果汁(二分答案+主席树)
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/13201025.html
Copyright © 2011-2022 走看看