【最小生成树】IOI2003maintain

来源:互联网 发布:发票数据管理软件 编辑:程序博客网 时间:2024/05/18 02:34

题目描述

在一个初始化为空的无向图中,不断加入新边。如果当前图连通,就求出当前图最小生成树的总权值;否则,输出-1。


分析

目前已知的算法中,破圈算法是最快的。
破圈算法顾名思义,把边按照输入顺序插入树中,如果该边的两端点在同一颗树里,再插入这条边一定会形成环。破圈算法就是把环上权值最大的边删去,就能够维持树的边权尽量小。

//破圈算法yhn(找cch要对拍程序的时候用他的号交了一遍。。)#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define SF scanf#define PF printfvoid Read(int &x){    x=0;    char c;    bool flag=0;    while(c=getchar(),c!=EOF&&(c<'0'||c>'9')&&c!='-');    if(c=='-'){flag=1;c=getchar();}    x=c-'0';    while(c=getchar(),c!=EOF&&c>='0'&&c<='9') x=x*10+c-'0';    if(flag==1)x=-x;}#define MAXN 210#define INF 0x3FFFFFFFusing namespace std;int fa[MAXN],f[MAXN],val[MAXN],vis[MAXN],last[MAXN];int get_fa(int x){    if(fa[x]==0)        return x;    fa[x]=get_fa(fa[x]);    return fa[x];}void update(int x,int y,int stop){    if(stop==x)        return ;    if(f[y]!=0)        update(y,f[y],stop);    val[y]=val[x];    f[y]=x;}int check(int x,int y,int z){    memset(vis,0,sizeof vis);    int maxl=-1,maxd,k;    int x1=x;    while(x1!=0){        vis[x1]=maxl;        last[x1]=maxd;        if(maxl<val[x1]){            maxl=val[x1];            maxd=x1;        }        x1=f[x1];    }    x1=y;    maxl=0;    while(x1!=0){        if(vis[x1]!=0){            if(maxl>vis[x1]){                vis[x1]=maxl;                last[x1]=maxd;                k=2;            }            else                k=1;            break;        }        vis[x1]=maxl;        last[x1]=maxd;        if(maxl<val[x1]){            maxl=val[x1];            maxd=x1;        }        x1=f[x1];    }    if(vis[x1]>z){        if(k==1){            update(y,x,last[x1]);            val[x]=z;        }        else{            update(x,y,last[x1]);            val[y]=z;        }    }    return max(vis[x1],z);}int sum,ins,n,m,x,y,z;int main(){    Read(n),Read(m);    for(int i=1;i<=m;i++){        Read(x),Read(y),Read(z);        int u=get_fa(x);        int v=get_fa(y);        if(u!=v){            ins++;            update(x,y,-1);            val[y]=z;            fa[v]=u;            sum+=z;        }        else{            int s=check(x,y,z);            sum=sum+z-s;        }        if(ins<n-1)            PF("-1\n");        else            PF("%d\n",sum);    }}