poj 3522 Slim Span (Kruskal+枚举)
题目大意: 在一个无向联通图中 求一棵最大边与最小边差值最小的生成树
解题思路: 最大边与最小边差值最小的生成树
换言之使得最小边与最大边的长度最接近
任取一条边为生成树最小的边,唯一存在一条最大边最接近最小的边
对所有的边从小到大排序
差值最小的最大边一定在最小边后面
并且是构成这个生成树的最后一条边!
枚举最小边到第m-n+2小边组成的生成树,找出差值最小的
易错点: 最小边和最大边可能是同一条边
代码:
[cpp]
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 101
#define MAX_2 9000
#define INF 0x3f3f3f3f
typedef struct snode{
int x;
int y;
int s;
}span;
int father[MAX];
int comp(const void *a,const void *b)
{
span *pa=(span *)a;
span *pb=(span *)b;
return pa->s-pb->s;
}
void Empty(int n)
{
int i;
for(i=1;i<=n;i++)
father[i]=i;
}
int Find(int x)
{
int s,j;
s=x;
while(x!=father[x]) x=father[x];
while(s!=x)
{
j=father[s];
father[s]=x;
s=j;
}
return x;
}
void Union(int R1,int R2)
{
int r1,r2;
r1=Find(R1);
r2=Find(R2);
if(r1!=r2) father[r1]=r2;
}
int main ()
{
int n,m,i,j,min,start,end,num,a;
while(scanf("%d%d",&n,&m)!=EOF)
{
span spantree[MAX_2];
if(m==0&&n==0)
break;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&spantree[i].x,&spantree[i].y,&spantree[i].s);
}
qsort(spantree,m,sizeof(spantree[0]),comp); //把边从小到大排序
for(i=0,end=0,start=0,min=INF;i<m-n+2;i++) //最多m-n+2个生成树
{
Empty(n);
for(j=i,num=0;j<m;j++)
{
if(Find(spantree[j].x)!=Find(spantree[j].y))
{
Union(spantree[j].x,spantree[j].y);
num++; //某个生成树的第num条边
if(num==1) //第一条最小,num-1条最大
start=spantree[j].s;
if(num==n-1) //易错点**:是if不是else if,因为可能只有一条边
end=spantree[j].s;
}
if(num==n-1)
{
a=end-start;
if(a<min)
{
min=a; //找到最小的差值
}
break;
}
}
}
if(min!=INF) printf("%d\n",min);
else printf("-1\n");
}
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 101
#define MAX_2 9000
#define INF 0x3f3f3f3f
typedef struct snode{
int x;
int y;
int s;
}span;
int father[MAX];
int comp(const void *a,const void *b)
{
span *pa=(span *)a;
span *pb=(span *)b;
return pa->s-pb->s;
}
void Empty(int n)
{
int i;
for(i=1;i<=n;i++)
father[i]=i;
}
int Find(int x)
{
int s,j;
s=x;
while(x!=father[x]) x=father[x];
while(s!=x)
{
j=father[s];
补充:软件开发 , C++ ,
- 更多C/C++疑问解答:
- 关于c++的cout输出的问题。
- 在学校里学过C和C++,不过学的很一般,现在自学C#,会不会很难?
- 全国计算机二级C语言笔试题
- 已知某树有2个2度结点,3个3度结点,4个4度结点,问有几个叶子结点?
- c++数据结构内部排序问题,整数排序
- 2012九月计算机二级C语言全国题库,,急求急求
- 如果assert只有一个字符串作为参数,是什么意思呢?
- C语言中,哪些运算符具有左结合性,哪些具有右结合性,帮忙总结下,谢谢了!
- 为什么用结构体编写的程序输入是,0输不出来啊~~~
- 将IEEE—754的十六进制转化为十进制浮点类型,用C或C++都行,多谢各位大侠啊,非常感谢!
- 为什么这个程序求不出公式?
- 这个链表倒置的算法请大家分析下
- c语言函数库调用
- C语言unsigned int纠错
- C语言快排求解啊