zoukankan      html  css  js  c++  java
  • [CF609E] Minimum spanning tree for each edge

    Description

    对无向图求其中每条边必须被选中时的最小生成树。

    Solution

    现任意求出一棵最小生成树,建树,树上倍增支持询问 LCA 和链最大值。

    如果选择的边是树枝则直接输出。如果是弦,则用这条弦换掉对应基本回路上的次大值,即对应树上路径上的最大值。

    (就当复习一下写树上倍增了)

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 200005;
    const int M = 20;
    const int dbg = 0;
    
    namespace tree
    {
        vector<pair<int,int>> g[N];
        int vis[N],fa[N][M],mx[N][M],dep[N];
    
        void make(int u,int v,int w)
        {
            g[u].push_back({v,w});
            g[v].push_back({u,w});
        }
    
        void dfs(int p)
        {
            vis[p]=1;
            for(auto pr:g[p])
            {
                int q=pr.first, w=pr.second;
                if(vis[q]==0)
                {
                    fa[q][0]=p;
                    mx[q][0]=w;
                    dep[q]=dep[p]+1;
                    dfs(q);
                }
            }
        }
    
        void presolve(int n)
        {
            dfs(1);
            for(int j=1;j<M;j++)
            {
                for(int i=1;i<=n;i++)
                {
                    fa[i][j]=fa[fa[i][j-1]][j-1];
                    mx[i][j]=max(mx[i][j-1], mx[fa[i][j-1]][j-1]);
                }
            }
        }
    
        int lca(int p,int q)
        {
            if(dep[p]<dep[q]) swap(p,q);
            for(int i=M-1;i>=0;--i) if(dep[fa[p][i]]>=dep[q]) p=fa[p][i];
            for(int i=M-1;i>=0;--i) if(fa[p][i]!=fa[q][i]) p=fa[p][i],q=fa[q][i];
            if(p!=q) p=fa[p][0],q=fa[q][0];
            return p;
        }
    
        int singlequery(int p,int q)
        {
            int ans=0;
            for(int i=M-1;i>=0;--i) if(dep[fa[p][i]]>=dep[q]) ans=max(ans,mx[p][i]),p=fa[p][i];
            return ans;
        }
    
        int query(int p,int q)
        {
            int l=lca(p,q);
            return max(singlequery(p,l),singlequery(q,l));
        }
    }
    
    namespace graph
    {
        int fa[N],ans;
    
        void init(int n)
        {
            for(int i=1;i<=n;i++) fa[i]=i;
        }
    
        int find(int p)
        {
            return p==fa[p] ? p : fa[p]=find(fa[p]);
        }
    
        bool isconnected(int p,int q)
        {
            p=find(p);
            q=find(q);
            return p==q;
        }
    
        void merge(int p,int q)
        {
            p=find(p);
            q=find(q);
            if(p!=q) fa[p]=q;
        }
    
        struct edge
        {
            int u,v,w;
            bool operator < (const edge &t)
            {
                return w < t.w;
            }
        } e[N];
    
        int m;
    
        void make(int u,int v,int w)
        {
            e[++m]={u,v,w};
        }
    
        void presolve(int n)
        {
            init(n);
            sort(e+1,e+m+1);
            for(int i=1;i<=m;i++)
            {
                edge &tmp=e[i];
                if(!isconnected(tmp.u,tmp.v))
                {
                    merge(tmp.u,tmp.v);
                    tree::make(tmp.u,tmp.v,tmp.w);
                    ans+=tmp.w;
                }
            }
    
            if(dbg) cout<<"MST answer = "<<ans<<endl;
        }
    }
    
    struct edge
    {
        int u,v,w;
        bool operator < (const edge &t)
        {
            return w < t.w;
        }
    } e[N];
    
    int n,m;
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n>>m;
        for(int i=1;i<=m;i++)
        {
            int t1,t2,t3;
            cin>>t1>>t2>>t3;
            e[i]={t1,t2,t3};
            graph::make(t1,t2,t3);
        }
        graph::presolve(n);
        tree::presolve(n);
        for(int i=1;i<=m;i++)
        {
            int tans=graph::ans;
            tans+=e[i].w;
            int tmp=tree::query(e[i].u,e[i].v);
            if(dbg) cout<<":: "<<e[i].u<<","<<e[i].v<<" = "<<tmp<<endl;
            tans-=tmp;
            cout<<tans<<endl;
        }
    }
    
    
  • 相关阅读:
    Monkey写脚本
    Appium+JAVA初试牛刀之安装APP
    新安家啦
    SRAM速度提升思路及方法
    FIR滤波器工作原理(算法)以及verilog算法实现(包含与IIR的一些对比)
    I2C总线协议详解
    有符号二进制加法溢出判断以及溢出后该如何计算正确答案
    Verilog 编写规范
    Android中锁屏密码算法解析以及破解方案
    IIS中查看W3P.exe进程对应的应用程序池的方法
  • 原文地址:https://www.cnblogs.com/mollnn/p/13625087.html
Copyright © 2011-2022 走看看