题目来源:HDU 1598
简单题目分析:
求A到B的所有路径中,最大权值和最小权值的差的最小值。
思路:枚举+贪心。先用结构体存储m条边,并按权值升序排列。依次从最小边枚举,逐渐加入边直到A与B连通(Kruskal的思想),每一次更新最小值即可。
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
using namespace std;
int n,m;
struct line //典型Kruskal存储信息的结构体,起点、终点和权值
{
int src;
int dest;
int len;
}temp[1005];
bool cmp(line a,line b)
{
return a.len<b.len;
}
int pre[205];
int findRoot(int x)
{
while(x!=pre[x])
x=pre[x];
return x;
}
bool isMerge(int a,int b) //判断a和b是否连通
{
int i;
bool flag;
for(i=0;i<m;++i)
pre[findRoot(temp[i].dest)]=findRoot(temp[i].src);
if(findRoot(a)==findRoot(b))
flag=true;
else
flag=false;
return flag;
}
void init() //注意并查集初始化的问题
{
int i;
for(i=1;i<=n;++i)
pre[i]=i;
}
int main()
{
while( ~scanf("%d %d",&n,&m) )
{
int i,j;
for(i=0;i<m;++i)
scanf("%d %d %d",&temp[i].src,&temp[i].dest,&temp[i].len);
sort(temp,temp+m,cmp);
int Q;
scanf("%d",&Q);
while(Q--)
{
int a,b;
int myMin=10000000;
scanf("%d %d",&a,&b);
if(isMerge(a,b))
{
init();
for(i=0;i<m;++i) //枚举m条最小边
{
init();
int ans=0;
for(j=i;j<m;++j)
{
pre[findRoot(temp[j].dest)]=findRoot(temp[j].src);
if(findRoot(a)==findRoot(b))
{
ans=temp[j].len-temp[i].len;
break;
}
}
if(findRoot(a)==findRoot(b))
{
if(ans<myMin)
myMin=ans;
}
else
continue;
}
printf("%d\n",myMin);
}
else
printf("-1\n");
}
}
return 0;
}