电话线铺设——难实现的最小生成树

电话线铺设

 

 

 

 

 

输入

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\n")
#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\n",ans);
    for(int i=1;i<=n-1;i++){
        if(anss[i]==where)continue;
        printf("%lld\n",anss[i]);
    }
    printf("%lld\n",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\n",sum+minn);
    for(int i=1;i<=n-2;i++)
    printf("%lld\n",anss[i]);
    printf("%lld\n",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;
}

 

posted @ 2020-08-02 09:03  zjy1412  阅读(162)  评论(4编辑  收藏  举报