bzoj1977 [BeiJing2010组队]次小生成树 倍增

来源:互联网 发布:网络运维工程师招聘 编辑:程序博客网 时间:2024/06/08 05:01

标准的次小生成树(严格次小)
先想想不严格怎么做(好像都差不多)
枚举每一条边来更新,这是n^2算法。
然后这题的话我们对于每一个点,预处理,倍增一下求他到他的第2^j个父亲所经过的边的最大值和次大值。
然后我们先求出最小生成树,然后对于最小生成树上相邻两个点之间所有边,记录最大值和所选的边的差,如果最大值和原来的边相等就换成次大值,最后答案就是最小生成树+最小差值。

#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=3e5+5;int head[N],f[N],dep[N],fa[N][17];int d1[N][17],d2[N][17];const int inf=0x7fffffff;struct node{    int x,y,z;    bool sel;}a[N];int next[N],go[N],val[N];int tot,n,m,cnt,mn=inf;;typedef long long ll;ll ans;bool cmp(node a,node b){    return a.z<b.z;}inline void add(int x,int y,int z){    go[++tot]=y;    val[tot]=z;    next[tot]=head[x];    head[x]=tot;} inline void ins(int x,int y,int z){    add(x,y,z);    add(y,x,z);}inline int find(int x){    return x==f[x]?x:find(f[x]);}inline void dfs(int x,int f){    fo(i,1,16)    {        if (dep[x]<(1<<i))break;        fa[x][i]=fa[fa[x][i-1]][i-1];        d1[x][i]=max(d1[x][i-1],d1[fa[x][i-1]][i-1]);        if (d1[x][i-1]==d1[fa[x][i-1]][i-1])            d2[x][i]=max(d2[x][i-1],d2[fa[x][i-1]][i-1]);        else        {            d2[x][i]=min(d1[x][i-1],d1[fa[x][i-1]][i-1]);            d2[x][i]=max(d2[x][i-1],d2[x][i]);            d2[x][i]=max(d2[x][i],d2[fa[x][i-1]][i-1]);        }     }     for(int i=head[x];i;i=next[i])    {        int v=go[i];        if (v!=f)        {            fa[v][0]=x;            d1[v][0]=val[i];            dep[v]=dep[x]+1;            dfs(v,x);        }    }}inline int lca(int x,int y){    if (dep[x]<dep[y])swap(x,y);    fd(i,16,0)    if (dep[fa[x][i]]>=dep[y])x=fa[x][i];    if (x==y)return x;    fd(i,16,0)    if (fa[x][i]!=fa[y][i])    {        x=fa[x][i];        y=fa[y][i];    }    return fa[x][0];}inline void cal(int x,int f,int v){    int mx1=0,mx2=0;    int t=dep[x]-dep[f];    fo(i,0,16)    {        if (t&(1<<i))        {            if(d1[x][i]>mx1)            {                mx2=mx1;                mx1=d1[x][i];            }            mx2=max(mx2,d2[x][i]);            x=fa[x][i];        }    }    if (mx1!=v)mn=min(mn,v-mx1);    else mn=min(mn,v-mx2);}inline void solve(int t,int v){    int x=a[t].x,y=a[t].y,f=lca(x,y);    cal(x,f,v),cal(y,f,v);}int main(){    scanf("%d%d",&n,&m);    fo(i,1,n)f[i]=i;    fo(i,1,m)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);    sort(a+1,a+1+m,cmp);    int count=0;    fo(i,1,m)    {        int fx=find(a[i].x),fy=find(a[i].y);        if (fx!=fy)        {            f[fx]=fy;            ans+=a[i].z;            a[i].sel=1;            ins(a[i].x,a[i].y,a[i].z);            count++;            if (count==n-1)break;        }    }    dfs(1,0);    fo(i,1,m)        if (!a[i].sel)solve(i,a[i].z);    printf("%lld\n",ans+mn);}
阅读全文
0 0
原创粉丝点击