zoukankan      html  css  js  c++  java
  • 最小生成树<lct>

    题解:

    lct动态维护最小生成树

    每次加边时若这两个之间不连通,那么直接连接

    如果这两个点联通,那么就找到这条边上的最大值

    如果这个大于当前边,就替换掉

    但是需要注意的是lct只能维护点,不能维护边

    所以可以把边弄成点

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define maxn 500000
    ll n,m,num,root,data[maxn],fa[maxn],
    leftson[maxn],rightson[maxn];
    ll v[maxn],aa[maxn],bb[maxn];
    bool rev[maxn];
    void down(ll x)
    {
      if (!rev[x]) return;
      swap(leftson[x],rightson[x]); rev[x]=0;
      rev[leftson[x]]^=1; rev[rightson[x]]^=1; 
    }
    int se(int x,int y,int z)
    {
      if (v[x]>=v[y]&&v[x]>=v[z]) return(x);
      else if (v[y]>=v[x]&&v[y]>=v[z]) return(y);
      else return(z);
    }
    void updata(ll x)
    {
        down(x);
        data[x]=se(x,data[leftson[x]],data[rightson[x]]);
    }
    void pushr(ll x)
    {
      rev[x]^=1;
    }
    bool pd(ll x)
    {
      ll y=fa[x];
      if (leftson[y]!=x&&rightson[y]!=x) return(false);
      else return(true);
    }
    void rotate(ll x,ll y)
    {
      ll father=fa[x];
      if (y==1)
      {
        rightson[father]=leftson[x];
        if (leftson[x]) fa[leftson[x]]=father;
      } else
      {
        leftson[father]=rightson[x];
        if (rightson[x]) fa[rightson[x]]=father;
      }
      fa[x]=fa[father];
      if (pd(father))
      {
        if (leftson[fa[father]]==father) 
          leftson[fa[father]]=x; else
          rightson[fa[father]]=x;
      }
      fa[father]=x;
      if (y==1) leftson[x]=father; else rightson[x]=father;
      updata(father); updata(x);
    }
    void dfs(ll x)
    {
      if (pd(x)) dfs(fa[x]);
      down(x);
    }
    void splay(ll x)
    {
      dfs(x);
      ll father=fa[x];
      while (pd(x))
      {
        if (!pd(father))
        {
          if (x==leftson[father]) rotate(x,2);
          else rotate(x,1);
        } else
        {
          if (father==leftson[fa[father]])
          {
            if (x==leftson[father]) 
              rotate(father,2),rotate(x,2);
            else rotate(x,1),rotate(x,2);
          } else
          {
            if (x==rightson[father])
              rotate(father,1),rotate(x,1);
            else rotate(x,2),rotate(x,1);
          }
        }
        father=fa[x];
      }
    }
    void access(ll x)
    {
      for (ll y=0;x;y=x,x=fa[x])
        splay(x),rightson[x]=y,updata(x);
    }
    void makeroot(ll x)
    {
      access(x);
      splay(x);
      pushr(x);
    }
    ll findroot(ll x)
    {
      access(x);
      splay(x);
      while (leftson[x]) x=leftson[x];
      return x;
    }
    void split(ll x,ll y)
    {
      makeroot(x);
      access(y);
      splay(y);
    }
    void link(ll x,ll y)
    {
      makeroot(x);
      if (findroot(y)!=x) fa[x]=y;
    }
    void cut(ll x,ll y)
    {
      makeroot(x);
      split(x,y);
      fa[x]=leftson[y]=0;
    }
    int main()
    {
      freopen("noip.in","r",stdin);
      freopen("noip.out","w",stdout);
      cin>>n>>m;
      int c,d,e;
      int cnt=0,num=0;
      for (int i=1;i<=m;i++)
      {
          cin>>c>>d>>e;
          makeroot(c);
        if (findroot(d)==c)
        { 
            split(c,d);
            int d1=data[d];
            if (v[d1]>e)
            {
              cut(aa[d1],d1); cut(bb[d1],d1); num-=(v[d1]-e);
              link(c,i+n); link(i+n,d); v[i+n]=e;
              aa[i+n]=c; bb[i+n]=d;
            }
          } else
          {
            cnt++; link(c,i+n); link(i+n,d); v[i+n]=e;
            aa[i+n]=c; bb[i+n]=d; num+=e;
        }
      }
      cout<<num;
      return 0;
    }
  • 相关阅读:
    玩转xss
    Anonim小白成长计划
    mssql注入与绕过
    了解mssql数据库
    2020年度学习规划
    access 注入
    bypasswaf 之报错注入
    bypasswaf之盲注
    sql注入常用函数与bypasswaf
    一篇关于数据库的另类操作
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8452394.html
Copyright © 2011-2022 走看看