• POJ 3522 最小差值生成树(LCT)


    题目大意:给出一个n个节点的图,求最大边权值减去最小边权值最小的生成树。

    题解

    Flash Hu大佬一如既往地强

    先把边从小到大排序

    然后依次加入每一条边

    如果已经连通就把路径上权值最小的边删去

    然后记得更新答案

    ps:不是很明白为啥我洛谷上吸了氧还跑得更慢了233

     1 //minamoto
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<iostream>
     5 #define inf 0x3f3f3f3f
     6 using namespace std;
     7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     8 char buf[1<<21],*p1=buf,*p2=buf;
     9 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    10 inline int read(){
    11     #define num ch-'0'
    12     char ch;bool flag=0;int res;
    13     while(!isdigit(ch=getc()))
    14     (ch=='-')&&(flag=true);
    15     for(res=num;isdigit(ch=getc());res=res*10+num);
    16     (flag)&&(res=-res);
    17     #undef num
    18     return res;
    19 }
    20 const int N=50005,M=200005,K=N+M;
    21 struct edge{
    22     int u,v,e;
    23     inline bool operator <(const edge &b)const
    24     {return e<b.e;}
    25 }e[M];
    26 int fa[K],ch[K][2],s[K],mn[K],rev[K],top,v[K],vis[M],f[N];
    27 int ff(int x){return f[x]==x?x:f[x]=ff(f[x]);}
    28 inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    29 inline int get(int x,int y){return v[x]<v[y]?x:y;}
    30 inline void pushup(int x){mn[x]=get(x,get(mn[ch[x][0]],mn[ch[x][1]]));}
    31 inline void pushdown(int x){
    32     if(x&&rev[x]){
    33         swap(ch[x][0],ch[x][1]);
    34         rev[ch[x][0]]^=1,rev[ch[x][1]]^=1;
    35         rev[x]=0;
    36     }
    37 }
    38 void rotate(int x){
    39     int y=fa[x],z=fa[y],d=ch[y][1]==x;
    40     if(!isroot(y)) ch[z][ch[z][1]==y]=x;
    41     fa[x]=z,fa[y]=x,fa[ch[x][d^1]]=y,ch[y][d]=ch[x][d^1],ch[x][d^1]=y,pushup(y);
    42 }
    43 void splay(int x){
    44     s[top=1]=x;for(int i=x;!isroot(i);i=fa[i]) s[++top]=fa[i];
    45     while(top) pushdown(s[top--]);
    46     for(int y=fa[x],z=fa[y];!isroot(x);y=fa[x],z=fa[y]){
    47         if(!isroot(y))
    48         ((ch[y][1]==x)^(ch[z][1]==y))?rotate(x):rotate(y);
    49         rotate(x);
    50     }
    51     pushup(x);
    52 }
    53 void access(int x){
    54     for(int y=0;x;x=fa[y=x])
    55     splay(x),ch[x][1]=y,pushup(x);
    56 }
    57 inline void makeroot(int x){
    58     access(x),splay(x),rev[x]^=1;
    59 }
    60 inline void link(int x){
    61     makeroot(e[x].u);
    62     fa[fa[e[x].u]=N+x]=e[x].v;
    63 }
    64 inline void cut(int x){
    65     access(e[x-N].u),splay(x);
    66     ch[x][0]=ch[x][1]=fa[ch[x][0]]=fa[ch[x][1]]=0;
    67     /*因为link的时候把u的父亲设为边,所以u的深度最低
    68     把它到根节点的路径打通就好了*/
    69 }
    70 int main(){
    71     //freopen("testdata.in","r",stdin);
    72     int n=read(),m=read();
    73     int ans=0;
    74     for(int i=0;i<=n;++i) f[i]=i,v[i]=inf;
    75     for(int i=1;i<=m;++i){
    76         int u=read(),v=read(),k=read();
    77         e[i]=(edge){u,v,k};
    78     }
    79     sort(e+1,e+1+m);
    80     for(int cnt=1,h=1,i=1;i<=m;++i){
    81         v[i+N]=e[i].e;
    82         int u,v;
    83         if(ff(u=e[i].u)!=ff(v=e[i].v)){
    84             vis[i]=1,link(i),f[f[u]]=f[v],++cnt;
    85             if(cnt==n) ans=e[i].e-e[h].e;
    86         }
    87         else{
    88             if(u==v) continue;
    89             vis[i]=1;
    90             makeroot(u),access(v),splay(v);
    91             vis[mn[v]-N]=0;while(!vis[h]) ++h;
    92             cut(mn[v]),link(i);
    93             if(cnt==n) cmin(ans,e[i].e-e[h].e);
    94         }
    95     }
    96     printf("%d
    ",ans);
    97     return 0;
    98 }
  • 相关阅读:
    基于范围的for循环
    ML.NET技术研究系列-2聚类算法KMeans
    SQLServer常用运维SQL整理
    ML.NET技术研究系列-1入门篇
    Kafka基本知识整理
    .NetCore技术研究-EntityFramework Core 3.0 Preview
    容器技术研究-Kubernetes基本概念
    特来电混沌工程实践-混沌事件注入
    .Net Core技术研究-Span<T>和ValueTuple<T>
    Visual Studio Git本地Repos和GitHub远程Repos互操作
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9417486.html
Copyright © 2020-2023  润新知