1. 程式人生 > >POJ 3522 最小差值生成樹(LCT)

POJ 3522 最小差值生成樹(LCT)

true 最小邊 isdigit ons data esp 如果 get moto

題目大意:給出一個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\n",ans); 97 return 0; 98 }

POJ 3522 最小差值生成樹(LCT)