• Hihocoder1883 : 生成树问题(并查集+树剖+线段树)


    描述

    有一个无向图,有n个点,m1条第一类边和m2条第二类边。第一类边有边权,第二类边无边权。请为第二类的每条边定义一个边权,使得第二类边可能全部出现在该无向图的最小生成树上,同时要求第二类边的边权总和尽可能大。
    注:第二类边不会形成环

    输入

    第一行三个数n,m2,m1

    接下来m2行,每行两个数,描述一条第二类边,分别表示两个端点接下来m1行,每行三个数,描述一条第一类边,分别表示两个端点和边权

    对于30%的数据,n ≤ 5

    对于60%的数据,n ≤ 1000

    对于100%的数据,1 ≤ n ≤ 100000, m1 ≤ 2 × n, m2 < n

    输出

    输出一个数,表示第二类边的权值总和最大可能为多少。(若可能为无穷大则输出-1)

    样例输入
    5 2 3
    1 2
    4 5
    2 3 100
    3 4 100
    1 5 1000
    样例输出
    2000

    思路:我们先把第二类(B)和第一类(A)按权值排序,生成一个最小生成树,那么,对于第一类里面的那些没有被加入到树里的边e,我们需要保证这些边的两端在树上的路径e.u->e.v上的所有A类边都不大于e.cost。

    所以我们需要去更新A类边的权值,我们把A类边都的权值都设为inf,然后用e.cost去更新,更新的过程就是势能线段树,如果区间有inf,那么就更新,否则跳过这个区间,因为每个A类边最多被跟新一次,势能会变小,这样可以保证复杂度。

     (开始一直在想持久化并查集或者LCT...赶脚做不出来,然后才写了这个又长又臭的代码。求更简单的方法。qwq

    (补充,好像不用线段树啊,直接用并查集找祖先里第一个A类边即可...

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=2000010;
    const int inf=1e9;
    int x[maxn],y[maxn],Laxt[maxn],Next[maxn],To[maxn],Len[maxn];
    int fa[maxn],Mx[maxn],tot,N,cnt,dep[maxn];
    int a[maxn],sz[maxn],son[maxn],Top[maxn],p[maxn],q[maxn];
    struct in{ int u,v,cost; }s[maxn];
    bool cmp(in p,in q){ return p.cost<q.cost;}
    int ff[maxn]; int find(int x){if(x==ff[x]) return x; return ff[x]=find(ff[x]);}
    void add(int u,int v,int c){
        Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=c;
    }
    void dfs1(int u,int f){
        dep[u]=dep[f]+1; fa[u]=f; sz[u]=1;
        for(int i=Laxt[u];i;i=Next[i])
           if(To[i]!=f) {
             dfs1(To[i],u),sz[u]+=sz[To[i]];
             a[To[i]]=Len[i];
             if(sz[To[i]]>sz[son[u]]) son[u]=To[i];
        }
    }
    void dfs2(int u,int top)
    {
        Top[u]=top; p[++tot]=u; q[u]=tot;
        if(son[u]) dfs2(son[u],top);
        for(int i=Laxt[u];i;i=Next[i]){
            if(To[i]!=son[u]&&dep[To[i]]>dep[u])
              dfs2(To[i],To[i]);
        }
    }
    void build(int Now,int L,int R)
    {
        if(L==R) { Mx[Now]=a[p[L]]; return ;}
        int Mid=(L+R)>>1;
        build(Now<<1,L,Mid); build(Now<<1|1,Mid+1,R);
        Mx[Now]=max(Mx[Now<<1],Mx[Now<<1|1]);
    }
    int query(int Now,int L,int R,int l,int r)
    {
        if(Mx[Now]<inf) return 0;
        if(L==R){Mx[Now]=0; return 1;}
        int Mid=(L+R)>>1,res=0;
        if(l<=Mid) res+=query(Now<<1,L,Mid,l,r);
        if(r>Mid) res+=query(Now<<1|1,Mid+1,R,l,r);
        Mx[Now]=max(Mx[Now<<1],Mx[Now<<1|1]);
        return res;
    }
    int Query(int u,int v)
    {
        int f1=Top[u],f2=Top[v],res=0;
        while(f1!=f2){
            if(dep[f1]<dep[f2]) swap(f1,f2),swap(u,v);
            res+=query(1,1,N,q[f1],q[u]);
            u=fa[f1]; f1=Top[u];
        }
        if(u!=v){
            if(dep[u]>dep[v]) swap(u,v);
            res+=query(1,1,N,q[son[u]],q[v]);
        }
        return res;
    }
    int main()
    {
        int A,B; ll ans=0;
        scanf("%d%d%d",&N,&A,&B);
        rep(i,1,N) ff[i]=i;
        rep(i,1,A){
            scanf("%d%d",&x[i],&y[i]);
            int fu=find(x[i]),fv=find(y[i]);
            ff[fu]=fv;
            add(x[i],y[i],inf); add(y[i],x[i],inf);
        }
        rep(i,1,B) scanf("%d%d%d",&s[i].u,&s[i].v,&s[i].cost);
        sort(s+1,s+B+1,cmp);
        rep(i,1,B) {
            int fu=find(s[i].u),fv=find(s[i].v);
            if(fu==fv) s[++tot]=s[i];
            else { ff[fu]=fv;
                add(s[i].u,s[i].v,s[i].cost);
                add(s[i].v,s[i].u,s[i].cost);
            }
        }
        B=tot; tot=0;
        dfs1(1,0); dfs2(1,1);
        build(1,1,N); tot=0;
        rep(i,1,B){
            tot=Query(s[i].u,s[i].v);
            ans+=(ll)tot*s[i].cost;
        }
        if(Mx[1]==inf) puts("-1");
        else printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    STL"源码"剖析
    Excel如何进行SVN
    BootstrapTable+KnockoutJS
    WebApi 集成 Swagger
    Java Core和HeapDump
    深入分析 Java 中的中文编码问题(1)
    Java编码浅析(注意区分三个概念)(转)
    理解并解决GBK转UTF-8奇数中文乱码(转)
    Java实现敏感词过滤(转)
    Android MediaPlayer状态机
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10209647.html
Copyright © 2020-2023  润新知