Description
因为一场不小的地震,Y 省n 个城市之间的道路都损坏掉了,省长希望小X 将城市之间的道路重修一遍。
很多城市之间的地基都被地震破坏导致不能修路了,因此可供修建的道路只有m 条。因为施工队伍有限,省长要求用尽量少的道路将所有的城市连通起来,这样施工量就可以尽量少。不过,省长为了表示自己的公正无私,要求在满足上述条件的情况下,选择一种方案,使得该方案中最贵道路的价格和最便宜道路的价格的差值尽量小,即使这样的方案会使总价提升很多也没关系。
小X 现在手忙脚乱,希望你帮帮他。
2 ≤ n ≤ 2000,0 ≤ m ≤ 15000
Solution
发现
O(nm)
可以过耶!
先把边按大小排个序,
对于每条边,扫一遍全局,看看有没有环,有的话把环上最小的边去掉,
每次判断一下是不是联通的,是则更新答案,
复杂度: O(nm+mlog(m))
Code
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define min(q,w) ((q)<(w)?(q):(w))
#define max(q,w) ((q)>(w)?(q):(w))
using namespace std;
const int N=2005;
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 n,m,ans,FD;
struct qqww
{
int x,y,v;
}b[N*8];
bool z[N*8];
int B[N*16][5],A[N],B0=1;
bool PX(qqww q,qqww w){return q.v<w.v;}
void DLT(int q)
{
if(B[q][3])B[B[q][3]][0]=B[q][0];
else A[B[q^1][1]]=B[q][0];
B[B[q][0]][3]=B[q][3];
}
void link(int q,int w,int e,int e1)
{
B[++B0][0]=A[q],B[A[q]][3]=B0,A[q]=B0,B[B0][1]=w,B[B0][2]=e,B[B0][4]=e1;
B[++B0][0]=A[w],B[A[w]][3]=B0,A[w]=B0,B[B0][1]=q,B[B0][2]=e,B[B0][4]=e1;
}
void dfs(int q,int fa,int zd,int mi)
{
if(q==zd){FD=mi;return;}
efo(i,q)if(B[i][1]!=fa)
{
if(B[i][2]>B[mi][2])dfs(B[i][1],q,zd,mi);
else dfs(B[i][1],q,zd,i);
if(FD)return;
}
}
int main()
{
int q,w,e;
read(n),read(m);
fo(i,1,m)read(b[i].x),read(b[i].y),read(b[i].v);
sort(b+1,b+1+m,PX);
ans=2e9;
int mi=1,x,y;
q=0;B[0][2]=1e9;
fo(i,1,m)
{
int x=b[i].x,y=b[i].y;
FD=0;
dfs(x,0,y,0);
if(!FD)q++;
else
{
z[B[FD][4]]=1;
DLT(FD),DLT(FD^1);
}
link(x,y,b[i].v,i);
while(z[mi])mi++;
if(q==n-1)ans=min(ans,b[i].v-b[mi].v);
}
if(ans==2e9)printf("-1\n");
else printf("%d\n",ans);
return 0;
}