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;
}

猜你喜欢

转载自www.cnblogs.com/lmjer/p/9396340.html
今日推荐