zoukankan      html  css  js  c++  java
  • 电话线铺设——难实现的最小生成树

    电话线铺设

     

     

    输入

    6 9 4
    6 3 4
    2 5 6
    5 4 6
    1 3 5
    3 5 9
    5 6 8
    4 1 5
    4 6 4
    6 2 7
    2 5 3
    1 5 4
    4 5 4
    3 2 5

    输出

    22
    1
    8
    4
    3
    1

    分析:

    这道题打完就A的感觉也太爽了吧,题解待会补,先上代码。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<vector>
    #include<cstdlib>
    using namespace std;
    #define debug printf("zjyvegetable
    ")
    #define int long long
    inline int read(){
        int a=0,b=1;char c=getchar();
        while(!isdigit(c)){if(c=='-')b=-1;c=getchar();}
        while(isdigit(c)){a=a*10+c-'0';c=getchar();}
        return a*b;
    }
    const int N=2e5+50,M=4e5+50,inf=12345678901234;
    struct node{
        int u,v,val,id;
    }ed[N],li[N];
    bool cmp(node x,node y){
        return x.val<y.val;
    }
    int n,W,l,t=30,tot,cnt,maxn,rem,sum,ans=inf,where,posi,d[N],F[N],
    f[N][33],g[N][33],wh[N][33],anss[N];
    int h[N],nx[M],ver[M],w[M],pos[M];
    int get(int x){
        if(F[x]==x)return x;
        else return F[x]=get(F[x]);
    }
    void mer(int x,int y){
        F[get(x)]=get(y);
    }
    void add(int u,int v,int z,int whe){
        ver[++cnt]=v;w[cnt]=z;pos[cnt]=whe;
        nx[cnt]=h[u];h[u]=cnt;
    }
    queue<int>q;
    void bfs(){
        d[1]=1;q.push(1);
        while(q.size()){
            int x=q.front();q.pop();
            for(int i=h[x];i;i=nx[i]){
                int v=ver[i];
                if(d[v])continue;
                q.push(v);
                d[v]=d[x]+1;
                f[v][0]=x;
                g[v][0]=w[i];
                wh[v][0]=pos[i];
                for(int j=1;j<=t;j++){
                    f[v][j]=f[f[v][j-1]][j-1];
                    if(g[v][j-1]>g[f[v][j-1]][j-1]){
                        g[v][j]=g[v][j-1];
                        wh[v][j]=wh[v][j-1];
                    }
                    else{
                        g[v][j]=g[f[v][j-1]][j-1];
                        wh[v][j]=wh[f[v][j-1]][j-1];
                    }
                }
            }
        }
    }
    void lca(int x,int y){
        maxn=0;
        if(d[x]>d[y])swap(x,y);
        for(int i=t;i>=0;i--){
            if(d[f[y][i]]>=d[x]){
                if(g[y][i]>maxn){
                    maxn=g[y][i];
                    rem=wh[y][i];
                }
                y=f[y][i];
            }
        }
        if(x==y)return;
        for(int i=t;i>=0;i--){
            if(f[y][i]!=f[x][i]){
                if(g[y][i]>maxn){
                    maxn=g[y][i];
                    rem=wh[y][i];
                }
                if(g[x][i]>maxn){
                    maxn=g[x][i];
                    rem=wh[x][i];
                }
                x=f[x][i];y=f[y][i];
            }
        }
        
        if(g[y][0]>maxn){
            maxn=g[y][0];
            rem=wh[y][0];
        }
        if(g[x][0]>maxn){
            maxn=g[x][0];
            rem=wh[x][0];
        }
    }
    void solve1(){
        bfs();
        for(int i=1;i<=l;i++){
            lca(li[i].u,li[i].v);
            if(sum-maxn+li[i].val<ans){
                ans=sum-maxn+li[i].val;
                where=rem;
                posi=i;
            }
        }
        printf("%lld
    ",ans);
        for(int i=1;i<=n-1;i++){
            if(anss[i]==where)continue;
            printf("%lld
    ",anss[i]);
        }
        printf("%lld
    ",posi);
        exit(0);
    }
    void solve2(){
        int x,y,minn=inf;
        for(int i=1;i<=l;i++){
            x=get(li[i].u);y=get(li[i].v);
            if(x==y)continue;
            if(li[i].val<minn){
                minn=li[i].val;
                rem=i;
            }
        }
        printf("%lld
    ",sum+minn);
        for(int i=1;i<=n-2;i++)
        printf("%lld
    ",anss[i]);
        printf("%lld
    ",rem);
        exit(0);
    }
    signed main(){
        freopen("telephone.in","r",stdin);
        freopen("telephone.out","w",stdout);
        n=read();W=read();l=read();
        for(int i=1;i<=W;i++){
            ed[i].u=read();
            ed[i].v=read();
            ed[i].val=read();
            ed[i].id=i;
        }
        for(int i=1;i<=n;i++)
        F[i]=i;
        int x,y;
        sort(ed+1,ed+W+1,cmp);
        for(int i=1;i<=W;i++){
            x=get(ed[i].u);y=get(ed[i].v);
            if(x==y)continue;
            mer(x,y);
            sum+=ed[i].val;
            add(ed[i].u,ed[i].v,ed[i].val,ed[i].id);
            add(ed[i].v,ed[i].u,ed[i].val,ed[i].id);
            anss[cnt/2]=ed[i].id;
        }
        for(int i=1;i<=l;i++){
            li[i].u=read();li[i].v=read();
            li[i].val=read();
        }
        if(cnt/2<n-1)solve2();
        else solve1();
        return 0;
    }
  • 相关阅读:
    数组、链表、Hash的优缺点
    数据库-索引的坏处,事务的级别,分布式事务的原理。
    4G内存的电脑,如何读取8G的日志文件进行分析,汇总数据成报表的面试题
    数据库常用的锁有哪些
    2020年最新 C# .net 面试题,月薪20K+中高级/架构师必看(十)
    ThreadX应用开发笔记之一:移植ThreadX到STM32平台
    net core 方法 返回值 重改?
    使用RestTemplate发送HTTP请求举例
    dedecms织梦手机站上一篇下一篇链接错误的解决方法
    多目标跟踪之数据关联(匈牙利匹配算法和KM算法)
  • 原文地址:https://www.cnblogs.com/zjy1412/p/13417685.html
Copyright © 2011-2022 走看看