• bzoj 2238 Mst——树链剖分


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2238

    一条非树边可以对一条链的树边产生影响。注意是边,所以把边下放到点上,只要跳 top 时不赋 lca 就行。

    然后WA*3。看看题解才知道有一开始图就不连通的情况!自己还是太嫩了……

    只有单点查询很方便用标记永久化。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=5e4+5,M=1e5+5;
    int n,m,q,hd[N],xnt,to[N<<1],nxt[N<<1],fa[N],ans;
    int tim,dfn[N],siz[N],dep[N],son[N],top[N];
    int tot,ls[N<<1],rs[N<<1],mn[N<<1];
    bool used[M],flag;
    struct Ed{
      int x,y,w,bh;
      Ed(int a=0,int b=0,int c=0,int d=0):x(a),y(b),w(c),bh(d) {}
      bool operator< (const Ed &b)const
      {return w<b.w;}
    }ed[M];
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    bool cmp(Ed u,Ed v){return u.bh<v.bh;}
    int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);}
    void add(int x,int y)
    {
      to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;
      to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt;
    }
    void dfs(int cr)
    {
      dep[cr]=dep[fa[cr]]+1; siz[cr]=1;
      for(int i=hd[cr],v;i;i=nxt[i])
        if((v=to[i])!=fa[cr])
          {
        fa[v]=cr; dfs(v); siz[cr]+=siz[v];
        siz[v]>siz[son[cr]]?son[cr]=v:0;
          }
    }
    void dfsx(int cr)
    {
      dfn[cr]=++tim;
      if(son[cr])top[son[cr]]=top[cr],dfsx(son[cr]);
      for(int i=hd[cr],v;i;i=nxt[i])
        if((v=to[i])!=fa[cr]&&v!=son[cr])
          top[v]=v,dfsx(v);
    }
    void build(int l,int r,int cr)
    {
      mn[cr]=M; if(l==r)return;
      int mid=l+r>>1;
      ls[cr]=++tot; build(l,mid,ls[cr]);
      rs[cr]=++tot; build(mid+1,r,rs[cr]);
    }
    void mdfy(int l,int r,int cr,int L,int R,int k)
    {
      if(l>=L&&r<=R){mn[cr]=min(mn[cr],k);return;}
      int mid=l+r>>1;
      if(L<=mid)mdfy(l,mid,ls[cr],L,R,k);
      if(mid<R)mdfy(mid+1,r,rs[cr],L,R,k);
    }
    void mdfy(int x,int y,int w)
    {
      while(top[x]!=top[y])
        {
          if(dep[top[x]]<dep[top[y]])swap(x,y);
          mdfy(1,n,1,dfn[top[x]],dfn[x],w);
          x=fa[top[x]];
        }
      if(x==y)return;//
      if(dep[x]<dep[y])swap(x,y);
      mdfy(1,n,1,dfn[son[y]],dfn[x],w);//son for no lca
    }
    int query(int l,int r,int cr,int p)
    {
      if(l==r)return mn[cr];
      int mid=l+r>>1;
      if(p<=mid)return min(query(l,mid,ls[cr],p),mn[cr]);
      else return min(query(mid+1,r,rs[cr],p),mn[cr]);
    }
    int main()
    {
      n=rdn();m=rdn();
      for(int i=1,u,v,z;i<=m;i++)
        {
          u=rdn(); v=rdn(); z=rdn();
          ed[i]=Ed(u,v,z,i);
        }
      for(int i=1;i<=n;i++)fa[i]=i;
      sort(ed+1,ed+m+1);
      for(int i=1,u,v;i<=m;i++)
        if((u=find(ed[i].x))!=(v=find(ed[i].y)))
          {
        used[ed[i].bh]=1; fa[u]=v;
        add(ed[i].x,ed[i].y); ans+=ed[i].w;
          }
      int d=find(1);
      for(int i=2;i<=n;i++)if(find(i)!=d){flag=1;break;}
      if(!flag)
        {
          sort(ed+1,ed+m+1,cmp);
          fa[1]=0; dfs(1); top[1]=1; dfsx(1); tot=1; build(1,n,1);
          for(int i=1;i<=m;i++)
        if(!used[i]) mdfy(ed[i].x,ed[i].y,ed[i].w);
        }
      q=rdn();
      for(int i=1,d;i<=q;i++)
        {
          d=rdn();
          if(flag){puts("Not connected");continue;}
          if(!used[d])printf("%d
    ",ans);
          else
        {
          int k=query(1,n,1,max(dfn[ed[d].x],dfn[ed[d].y]));//ed[d]!
          if(k==M)puts("Not connected");
          else printf("%d
    ",ans-ed[d].w+k);//ed[d]!
        }
        }
      return 0;
    }
  • 相关阅读:
    激活程序进程并显示最前
    ClickOnce 部署 API 以编程方式检查应用程序更新
    管理员权限运行
    扩展支持全选的CheckBox列。
    转 winfrom组件圆角
    转 无边框四周阴影
    转 实现类似QQ的窗体停靠
    关闭ShowDialog的模态窗口
    TextBox 显示横线
    转 无损转换Image为Icon
  • 原文地址:https://www.cnblogs.com/Narh/p/9801940.html
Copyright © 2020-2023  润新知