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 }
原文地址:https://www.cnblogs.com/bztMinamoto/p/9417486.html