Description
、
solution
这不就是LCT板子题嘛
每次暴力找出路径上最早的一条边,记录下来,把那条边断掉,连上这条边;
最后再从开头开始,往后找到第一个位置,使之成为一颗最小生成树,
再把第一条边去掉,继续往后找到记录值为1的边,
复杂度: O(nlog(n))
Code
#include <cstdio>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define efo(i,q) for(int i=A[q],i1=0;i;i1=i,i=B[i][0])
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
using namespace std;
const int N=4500,INF=2147483640;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans;
int g[N],b[N],bi[N];
struct qqww
{
int x,y,v;
}a[N];
int B[2*N][4],A[N],B0;
bool PX(qqww q,qqww w){return q.v<w.v;}
int gf(int q){return g[q]==q?q:(g[q]=gf(g[q]));}
void link(int q,int w,int e)
{
B[++B0][0]=A[q];A[q]=B0,B[B0][1]=w,B[B0][2]=e,B[B0][3]=0;
B[++B0][0]=A[w];A[w]=B0,B[B0][1]=q,B[B0][2]=e,B[B0][3]=0;
}
int mx,OK;
void dfs(int q,int fa,int T)
{
if(q==T){OK=1;return;}
for(;B[A[q]][3];A[q]=B[A[q]][0]);
efo(i,q)if(B[i][3])B[i1][0]=B[i][0],i=i1;
else if(B[i][1]!=fa)
{
dfs(B[i][1],q,T);
if(OK)
{
if(B[mx][2]>B[i][2])mx=i;
return;
}
}
}
int main()
{
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);
int q,w,_;
read(_);
B[0][2]=1e9;
while(_--)
{
read(n),read(m);
fo(i,1,m)read(a[i].x),read(a[i].y),read(a[i].v);
sort(a+1,a+1+m,PX);
ans=1e9;B0=1;
fo(i,1,n)g[i]=i,A[i]=0;
q=0;
fo(i,1,m)
{
// printf("%d %d %d\n",i,a[i].x,a[i].y);
int x=gf(a[i].x),y=gf(a[i].y);
if(x!=y)g[x]=y,q++,w=i,b[i]=0;
else
{
mx=OK=0;
dfs(a[i].x,0,a[i].y);
B[mx][3]=1;
B[mx^1][3]=1;
b[i]=B[mx][2];
}
link(a[i].x,a[i].y,i);
}
if(q<n-1){printf("-1\n");continue;}
fo(i,1,n)g[i]=i;
q=0;
fod(i,m,1)
{
int x=gf(a[i].x),y=gf(a[i].y);
if(x!=y)g[x]=y,q++,w=i;
if(q==n-1)break;
}
int j=m+1;bi[j]=1e9;
for(;bi[j];j--,bi[j]=min(b[j],bi[j+1]));
fo(i,1,w)
{
for(;bi[j]<i;j++);
ans=min(ans,a[j-1].v-a[i].v);
}
printf("%d\n",ans);
}
return 0;
}