题目描述
给定一个无向图,要求图中一个生成树,这个生成树中的最大边和最小边相差最小,输出这个差值
输入
第1行:输入两个整数n, m (3 ≤ n ≤ 300, 0 < m ≤ n*(n-1)/2),表示该组样例中点和边的个数,
之后每行三个整数x, y, s (0 ≤ x ≤ n-1, 0 ≤ y ≤ n-1, 1 ≤ s ≤ 10000),表示编号为x和编号为y的点之间有一条长度为s的边相连,保证给定的图联通,任意两点之间只有一条边相连
输出
输出最小差值,具体格式见sample
样例输入
【样例1】
3 3
0 1 220
1 2 120
2 0 160
【样例2】
4 5
2 3 80
1 3 80
0 1 180
2 1 200
3 0 140
样例输出
【样例1】
40
【样例2】
60
提示
数据范围 n m
1 ≤10 ≤45
2 ≤10 ≤45
3 ≤100 ≤4950
4 ≤100 ≤4950
5 ≤300 ≤20000
6 ≤300 ≤20000
7 ≤300 ≤44850
8 ≤300 ≤44850
9 ≤300 ≤44850
10 ≤300 ≤44850
想法
- codevs1001 将边排序
- 枚举起点不断将点加入最小生成树
- 反过来再跑一遍
算法
- 简单的kruskal
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#define MAXN 45011
#define INF 100000
using namespace std;
int n,m,tot,fa[305],ma,mi,ans,j,cnt;
//bool flag[MAXN];
struct Node
{
int u,v,w,next;
}edge[MAXN];
inline bool cmp(Node a,Node b)
{
return a.w<b.w;
}
inline int find(int a)
{
if(fa[a]!=a)return find(fa[a]);
else return fa[a];
}
int main()
{
//freopen("tree.in","r",stdin);
//freopen("tree.out","w",stdout);
scanf("%d%d",&n,&m);
ans=INF;
for (int i=1;i<=m;i++)
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
sort(edge+1,edge+1+m,cmp);
for (int i=1;i<=m;)
{
mi=ma=-1;
for (int k=0;k<n;k++)fa[k]=k;
cnt=0;
for (j=i;j<=m;j++)
{
int s=edge[j].u,t=edge[j].v;
s=find(s),t=find(t);
if(s!=t)
{
fa[s]=t,cnt++;
if(cnt==n-1)
{
ma=edge[j].w;
break;
}
}
}
if(ma==-1)break;
cnt=0;
for (int k=0;k<n;k++)fa[k]=k;
for (;j;j--)
{
//printf("%d\n",j);
int s=edge[j].u,t=edge[j].v;
s=find(s),t=find(t);
if(s!=t)
{
fa[s]=t,cnt++;
if(cnt==n-1)
{
mi=edge[j].w;
i=j+1;
break;
}
}
}
//printf("%d %d\n",mi,ma);
if(mi==-1)break;
ans=min(ans,ma-mi);
}
cout<<ans<<endl;
return 0;
}