最小差值生成树,自己学校oj通过,洛谷MLE90分
查看原帖
最小差值生成树,自己学校oj通过,洛谷MLE90分
104324
abruce楼主2020/5/28 20:54
#include<bits/stdc++.h>
using namespace std;
namespace io {
	inline int read() {
		int __x=0,__f=1;
		char __c=getchar();
		while(__c<'0'||__c>'9') {
			if(__c=='-')__f=-1;
			__c=getchar();
		}
		while(__c>='0'&&__c<='9') {
			__x=__x*10+__c-'0';
			__c=getchar();
		}
		return __x*__f;
	}
	char __F[200];
	inline void write(int __x) {
		if(__x==0) {
			putchar('0');
			return;
		}
		int __tmp,__cnt=0;
		if(__x>0) {
			__tmp=__x;
		} else {
			__tmp=-__x;
		}
		if(__x<0) {
			putchar('-');
		}
		while(__tmp>0) {
			__F[__cnt++]=__tmp%10+'0';
			__tmp/=10;
		}
		while(__cnt>0) {
			putchar(__F[--__cnt]);
		}
	}
}
using namespace io;
const int maxn=200005;
int c[maxn][2],f[maxn],rev[maxn],sum[maxn],v[maxn],book[maxn],n,m,cnt,minn=INT_MAX;
struct edge {
	int u,v,w1,w2;
} e[maxn*4];
bool cmp(edge a,edge b) {
	return a.w1<b.w1;
}
void pushdown(int x) {
	if(rev[x]) {
		rev[c[x][0]]^=1;
		rev[c[x][1]]^=1;
		rev[x]=0;
		swap(c[x][0],c[x][1]);
	}
}
void pushup(int x) {
	sum[x]=x;
	if(v[sum[c[x][0]]]<v[sum[x]]) {
		sum[x]=sum[c[x][0]];
	}
	if(v[sum[c[x][1]]]<v[sum[x]]) {
		sum[x]=sum[c[x][1]];
	}
}
bool isroot(int x) {
	return (c[f[x]][0]!=x)&&(c[f[x]][1]!=x);
}
void pushtag(int x) {
	if(!isroot(x)) {
		pushtag(f[x]);
	}
	pushdown(x);
}
void rotate(int x) {
	int y=f[x],z=f[y],l=c[y][0]!=x,r=l^1;
	if(!isroot(y)) {
		c[z][c[z][0]!=y]=x;
	}
	f[x]=z;
	f[y]=x;
	f[c[x][r]]=y;
	c[y][l]=c[x][r];
	c[x][r]=y;
	pushup(y);
	pushup(x);
}
void splay(int x) {
	pushtag(x);
	while(!isroot(x)) {
		int y=f[x],z=f[y];
		if(!isroot(y)) {
			if(c[z][0]==y^c[y][0]==x) {
				rotate(x);
			} else {
				rotate(y);
			}
		}
		rotate(x);
	}
}
void access(int x) {
	for(register int i=0; x; i=x,x=f[x]) {
		splay(x);
		c[x][1]=i;
		pushup(x);
	}
}
void makeroot(int x) {
	access(x);
	splay(x);
	rev[x]^=1;
}
int findroot(int x) {
	access(x);
	splay(x);
	while(c[x][0]) {
		x=c[x][0];
	}
	return x;
}
void split(int x,int y) {
	makeroot(x);
	access(y);
	splay(y);
}
void link(int x,int y) {
	makeroot(x);
	f[x]=y;
}
void cut(int x,int y) {
	split(x,y);
	if(c[y][0]==x)c[y][0]=f[x]=0;
}
int getf(int x,int y) {
	makeroot(x);
	return findroot(y)!=x;
}
int query(int x,int y) {
	split(x,y);
	return sum[y];
}
void kruskal() {
	int add=0,z,last=1;
	for(register int i=1; i<=n; i++) {
		v[i]=INT_MAX;
	}
	v[0]=INT_MAX;
	sort(e+1,e+m+1,cmp);
	for(register int i=1; i<=m; i++) {
		v[i+n]=e[i].w2;
		if(e[i].u==e[i].v) {
			book[i]=1;
			continue;
		}
		if(getf(e[i].u,e[i].v)) {
			link(e[i].u,i+n);
			link(i+n,e[i].v);
			add++;
		} else {
			z=query(e[i].u,e[i].v);
			book[z-n]=1;
			splay(z);
			f[c[z][0]]=f[c[z][1]]=0;
			link(e[i].u,i+n);
			link(i+n,e[i].v);
		}
		while(book[last]&&last<=i) {
			last++;
		}
		if(add>=n-1) {
			minn=min(minn,e[i].w1-e[last].w1);
		}
	}
}
int main() {
	n=read(),m=read();
	for(register int i=1; i<=m; i++) {
		e[i].u=read(),e[i].v=read(),e[i].w2=e[i].w1=read();
		sum[i+n]=i+n;
	}
	kruskal();
	write(minn);
	return 0;
}
2020/5/28 20:54
加载中...