• bzoj 1977 [BeiJing2010组队]次小生成树 Tree


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

    kruscal别忘了先按边权sort。自己觉得那部分处理得还挺好的。(联想到之前某题的经验)

    没管重边。好像还行?

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=1e5+5,M=3e5+5,Lm=20,INF=1e9+7;
    int n,m,head[N],xnt=1,pre[N][Lm+5],mx[N][Lm+5][2];
    int fa[N],dis[N],fr[N],dep[N];
    ll ans,zl;
    bool vis[N],use[M<<1];
    struct Ed{
      int next,fr,to,w,bh;
      Ed(int n=0,int f=0,int t=0,int w=0):next(n),fr(f),to(t),w(w) {}
      bool operator< (const Ed &b)const
          {return bh<b.bh;}
    }ed[M<<1];
    void add(int x,int y,int z)
    {
      ed[++xnt]=Ed(head[x],x,y,z);head[x]=xnt;ed[xnt].bh=xnt;
      ed[++xnt]=Ed(head[y],y,x,z);head[y]=xnt;ed[xnt].bh=xnt;
    }
    int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);}
    bool cmp(Ed u,Ed v){return u.w<v.w;}
    void kruscal()
    {
        sort(ed+2,ed+xnt+1,cmp);////////
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=2;i<=xnt;i++)
            if(find(ed[i].fr)!=find(ed[i].to))
            {
                use[ed[i].bh]=1;ans+=ed[i].w;
                fa[find(ed[i].fr)]=find(ed[i].to);
            }
        sort(ed+2,ed+xnt+1);//为了^1 
        for(int i=2;i<=xnt;i++)if(use[i])use[i^1]=1;
    }
    void dfs(int cr,int r)
    {
      pre[cr][0]=ed[r].fr;mx[cr][0][0]=ed[r].w;dep[cr]=dep[ed[r].fr]+1;
      for(int i=1;i<=Lm;i++)
        {
          int k=pre[cr][i-1];if(!pre[k][i-1])break;
          pre[cr][i]=pre[k][i-1];
          mx[cr][i][0]=max(mx[cr][i-1][0],mx[k][i-1][0]);
          mx[cr][i][1]=max(mx[cr][i-1][1],mx[k][i-1][1]);
          if(mx[cr][i-1][0]<mx[cr][i][0])mx[cr][i][1]=max(mx[cr][i][1],mx[cr][i-1][0]);
          if(mx[k][i-1][0]<mx[cr][i][0])mx[cr][i][1]=max(mx[cr][i][1],mx[k][i-1][0]);
        }
      for(int i=head[cr];i;i=ed[i].next)
        if(use[i]&&i!=(r^1)/*&&!pre[ed[i].to][0]*/)dfs(ed[i].to,i);
    }
    void cz(int &w0,int &w1,int x,int i)
    {
      int tmp=w0;
      w0=max(w0,mx[x][i][0]);w1=max(w1,mx[x][i][1]);
      if(tmp<w0)w1=max(w1,tmp);
      else if(mx[x][i][0]!=w0)w1=max(w1,mx[x][i][0]);//严格次大 
    }
    void solve(int x,int y,int &w0,int &w1)
    {
      if(dep[x]<dep[y])swap(x,y);
      for(int i=Lm;i>=0;i--)
        if(dep[pre[x][i]]>=dep[y])
          cz(w0,w1,x,i),x=pre[x][i];
      if(x==y)return;
      for(int i=Lm;i>=0;i--)
        if(pre[x][i]!=pre[y][i])
          {
        cz(w0,w1,x,i);cz(w0,w1,y,i);
        x=pre[x][i];y=pre[y][i];
          }
      if(x!=y)
        {
          cz(w0,w1,x,0);cz(w0,w1,y,0);
          x=pre[x][0];y=pre[y][0];
        }
    }
    int main()
    {
      scanf("%d%d",&n,&m);int x,y,z;
      for(int i=1;i<=m;i++)
        {
          scanf("%d%d%d",&x,&y,&z);add(x,y,z);
        }
      kruscal();
      dfs(1,0);zl=INF;
      for(int i=2;i<=xnt;i+=2)
        if(!use[i])
          {
        int w0=-1,w1=-1;
        solve(ed[i].fr,ed[i].to,w0,w1);
        if(ed[i].w>w0)zl=min(zl,(ll)ed[i].w-w0);
        else if(ed[i].w>w1)zl=min(zl,(ll)ed[i].w-w1);
          }
      printf("%lld",ans+zl);
      return 0;
    }
  • 相关阅读:
    JQuery 绑定单击事件到某个函数的的方法
    一刻校园足球管理平台亮相安徽打造智慧足球解决方案
    jQuery 获取不到 kindeditor 内容 的解决方法
    【视频】 ASP.NET MVC5&微信公众平台整合开发实战
    Set authorization for a whole area
    生成Area URL链接
    在ASP.NET MVC5应用程序中快速接入QQ和新浪微博OAuth
    IOS 监听通讯录是否改变
    ios 读取通讯录数据
    iOS中assign、copy 、retain等关键字的含义
  • 原文地址:https://www.cnblogs.com/Narh/p/9275960.html
Copyright © 2020-2023  润新知