邊權差值最小的生成樹
阿新 • • 發佈:2019-01-10
題目p1223
https://www.luogu.org/problemnew/show/P4234
程式碼
小資料版
使用Kruskal演算法的評測結果:
https://www.luogu.org/recordnew/show/15314074
//小資料版 已經極致優化,然而還是T掉最後一個點,T_T
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
char buf[1<<15],*fs,*ft;
inline char getc(){return (ft==fs&& (ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++;}
inline int read()
{
int num=0,f=1;char ch=getchar();
while (!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); }
while (isdigit(ch)) num=(num<<3)+(num<<1)+(ch^48), ch=getchar();
return num*f;
}
inline void print(int x)//快寫
{
if (x<0)
putchar('-'),x=-x;
if (x>9)
print(x/10);
putchar(x%10+48);
return ;
}
struct rec
{
int x,y,z;
}edge[maxn];
int fa[maxn],ans;
inline bool operator < (rec a,rec b)
{
return a.z<b.z;
}
inline int get(int x)
{
if (x==fa[x]) return x;
return fa[x]=get(fa[x]);
}
int main()
{
int n=read(),m=read(),i=0;
if (n==1)
{
puts("0");
exit(0);
}
for (i=1;i<=m;++i)
edge[i].x=read(),edge[i].y=read(),edge[i].z=read();
sort(edge+1,edge+m+1);
ans=edge[m].z;//差值初始化
for (int k=1;k<=m;++k)//以k為最小邊進行列舉
{
int sum=0;//最小生成樹的邊數
for (i=1;i<=n;++i)//生成樹初始化
fa[i]=i;
for (i=k;i<=m;++i)//求最小生成樹
{
int x=get(edge[i].x);
int y=get(edge[i].y);
if (x==y) continue;
fa[x]=y;
++sum;
if (sum==n-1)//已構成一個最小生成樹(從定義出發)
{
ans=min(ans,edge[i].z-edge[k].z);//最大邊減去最小邊
break;
}
}
if (i==m+1) break;
}
if (ans==edge[m].z)//ans未經過改變,說明此圖未連通
puts("-1");
else
print(ans);
return 0;
}
正解
一個叫做LCT的神奇演算法,評測結果:
https://www.luogu.org/recordnew/show/15314276
#include<bits/stdc++.h>
#define up(i,a,b) for (register int i=a;i<=b;++i)
#define down(i,a,b) for (register int i=a;i>=b;--i)
using namespace std;
template<typename T>inline void read(T &x)
{
T s=0,f=1;
char ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (!isdigit(ch)) { f=-1; ch=getchar(); }
while (isdigit(ch)) s=(s<<1)+(s<<3)+(ch^48), ch=getchar();
x=s*f;
}
static int n,m;
const int maxn=8e5+7;
static struct edge
{
int u,v,w;
friend bool operator < (edge a,edge b)
{
return a.w>b.w;
}
}q[maxn];
inline void init()
{
read(n),read(m);
if (n==1)
{
puts("0");
exit(0);
}
for (register int i=1;i<=m;++i)
{
read(q[i].u),read(q[i].v),read(q[i].w);
if (q[i].u==q[i].v)
--i,--m;
}
sort(q+1,q+m+1);
}
namespace LCT
{
int p[maxn],son[maxn][2],fa[maxn],key[maxn],rev[maxn];
inline bool isroot(int x)
{
return x!=son[fa[x]][0] && x!=son[fa[x]][1];
}
inline void refresh(int x)
{
p[x]=p[ son[x][ key[ p[son[x][0]] ]>key[ p[son[x][1]] ] ? 0 : 1 ] ];
if (key[x]>key[p[x]])
p[x]=x;
}
inline bool isl(int x)
{
return x^son[fa[x]][0];
}
inline void rotate(int x)
{
static int f,ff,ke;
f=fa[x],ff=fa[f],ke=isl(x);
fa[x]=ff;
if (!isroot(f))
son[ff][isl(f)]=x;
son[ fa[son[x][ke^1]]=f ][ke]=son[x][ke^1];
son[ fa[f]=x ][ke^1]=f;
refresh(f),refresh(x);
}
inline void pushdown(int x)
{
if (rev[x])
swap(son[x][0],son[x][1]),
rev[son[x][0]]^=1,rev[son[x][1]]^=1,
rev[x]=0;
}
static int sta[maxn];
inline void splay(int x)
{
static int t,top,f;
sta[top=1]=x;
for (t=x;!isroot(t);t=fa[t])
sta[++top]=fa[t];
for (;top;--top)
pushdown(sta[top]);
for (f=fa[x];!isroot(x);rotate(x),f=fa[x])
if (!isroot(f))
rotate(isl(x)^isl(f)?x:f);
}
inline void access(int x)
{
static int t;
for(t=0;x;t=x,x=fa[x])
splay(x),son[x][1]=t,refresh(x);
}
inline void makeroot(int x)
{
access(x),splay(x),rev[x]^=1;
}
inline void link(int x,int y)
{
makeroot(x),fa[x]=y;
}
inline void cut(int x,int y)
{
makeroot(x),access(y),splay(y);
son[y][0]=fa[x]=0,refresh(y);
}
inline int find(int x)
{
access(x),splay(x);
while (son[x][0]) x=son[x][0];
return x;
}
}
using namespace LCT;
multiset<int,greater<int> >G;
multiset<int,greater<int> >::iterator it;
#define Chkmin(a,b) a=a<b?a:b
inline void solve()
{
static int ans=200000,cnt=0,poi;
up (i,1,m)
key[i+n]=q[i].w;
up (i,1,m)
{
if (find(q[i].u)==find(q[i].v))
{
makeroot(q[i].u),access(q[i].v),splay(q[i].v);
poi=p[q[i].v];
cut(poi,q[poi-n].u);
cut(poi,q[poi-n].v);
key[poi]=0;
it=G.lower_bound(q[poi-n].w);
G.erase(it);
}
else ++cnt;
link(q[i].u,i+n);
link(q[i].v,i+n);
G.insert(q[i].w);
if (cnt==n-1)
Chkmin(ans,*G.begin()-q[i].w);
}
printf("%d\n",ans);
}
int main()
{
init();
solve();
return 0;
}