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;
        }
    };
    
  • 相关阅读:
    BEGIN2 序列求和
    BEGIN2 序列求和
    《算法竞赛入门经典》 习题45 IP网络(IP Networks,ACM、ICPC NEERC 2005,UVa1590)
    C#中char空值的几种表示方式
    C#中char空值的几种表示方式
    C#中() =>是什么意思
    C#中() =>是什么意思
    C# Task 暂停与取消
    C# Task 暂停与取消
    C# WinForm设置透明
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/13201025.html
Copyright © 2011-2022 走看看