• poj1977(次小生成树)


    这道题。。。

    中间发生了许多曲折离奇的故事。。。

    讲出来你可能不信。。

    我写了一整天

    主要思想为先找到最小生成树,,再拿不属于最小生成树的边替换,,最后可换出次小生成树

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    
    struct my{
           int next;
           int v;
           int w;
    };
    
    const int maxn=600000+10;
    const int maxm=600000+10;
    
    struct lmjer{int x,y,w;};
    struct node{int fa,a,b;}f[maxn][30];
    
    int adj[maxn],d[maxn],tot,n,m,fa[maxn],out[maxn],t;
    int vis[maxn];
    long long mst;
    lmjer a[maxm];
    my bian[maxm];
    queue<int>q;
    
    void myinsert(int u,int v,int w){
         bian[++tot].v=v;
         bian[tot].next=adj[u];
         bian[tot].w=w;
         adj[u]=tot;
    }
    
    bool cmp(const lmjer &x,const lmjer &y){
         return x.w<y.w;
    }
    
    int getfa(int x){
        if(x==fa[x]) return x;
        return fa[x]=getfa(fa[x]);
    }
    
    void kruskal(){
         for (int i=1;i<=n+10000;i++) fa[i]=i;
         for (int i=1;i<=m;i++){
            int x=getfa(a[i].x);
            int y=getfa(a[i].y);
            if(x!=y){
                mst+=a[i].w;
                fa[y]=x;
                myinsert(a[i].x,a[i].y,a[i].w);
                myinsert(a[i].y,a[i].x,a[i].w);
            }
            else out[i]=1;
         }
    }
    
    node init(int fa,int x,int y){
         node p;
         p.a=x,p.b=y,p.fa=fa;
         return p;
    }
    
    void calc(node &p,int x){
         if(x>p.a) p.b=p.a,p.a=x;
         if(x>p.b&&x<p.a) p.b=x;
    }
    
    node update(node x,node y){
         node p=y;
         calc(p,x.a);
         calc(p,x.b);
         return p;
    }
    
    void bfs(){
         for (int i=1;i<=n;i++){
            for (int j=0;j<=t;j++){
                f[i][j]=init(-1,-1,-1);
            }
         }
         q.push(1);
         vis[1]=1;
         while(!q.empty()){
            int x=q.front();
            q.pop();
            for (int i=adj[x];i;i=bian[i].next){
                int v=bian[i].v;
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                    f[v][0]=init(x,bian[i].w,-1);
                    d[v]=d[x]+1;
                    for (int j=1;j<=t;j++){
                        int z=f[v][j-1].fa;
                        if(z==-1) break;
                        f[v][j]=update(f[v][j-1],f[z][j-1]);
                    }
                }
            }
         }
    }
    
    node lca(int x,int y){
         node temp=init(-1,-1,-1);
         if(d[x]<d[y]) swap(x,y);
         for (int i=t;i>=0;i--){
              if(d[x]-(1<<i)>=d[y]){
                temp=update(temp,f[x][i]);
                x=f[x][i].fa;
              }
         }
         if(x==y) return temp;
         for (int i=t;i>=0;i--){
            if(f[x][i].fa!=f[y][i].fa){
                temp=update(temp,f[x][i]);
                temp=update(temp,f[y][i]);
                x=f[x][i].fa;
                y=f[y][i].fa;
            }
         }
         temp=update(temp,f[x][0]);
         temp=update(temp,f[y][0]);
         return temp;
    }
    
    int main(){
       // freopen("bzoj1977.in","r",stdin);
       // freopen("bzoj1977.out","w",stdout);
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++){
            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
        }
        t=(int)(log(n)/log(2));
        sort(a+1,a+1+m,cmp);
        kruskal();
        bfs();
        int ans=0x7f7f7f7f;
        for (int i=1;i<=m;i++){
            if(out[i]){
                node tmp=lca(a[i].x,a[i].y);
                if(a[i].w==tmp.a&&tmp.b!=-1) ans=min(ans,a[i].w-tmp.b);
                if(a[i].w>tmp.a) ans=min(ans,a[i].w-tmp.a);
            }
        }
        cout<<mst+ans<<endl;
    return 0;
    }
  • 相关阅读:
    每天一个linux命令(6):mv命令
    每天一个linux命令(5):rm 命令
    每天一个linux命令(4):mkdir命令
    每天一个linux命令(3):pwd命令
    每天一个linux命令(2):cd命令
    每天一个linux命令(1):ls命令
    Linux下svn命令详解
    Linux下SVN安装配置
    SVN命令使用详解
    分布式Web服务器架构
  • 原文地址:https://www.cnblogs.com/lmjer/p/9396340.html
Copyright © 2020-2023  润新知