题解:对于输入的边,我们首先按照速度从大到小排序,然后对于每一次询问,st end 两个城市,我们暴力枚举,
for(int i = 0; i < M; i ++) 然后我们从第 i 条边开始(也就是说枚举删除0~i条边),到后面的第 M 条边,我们用krustra,向并查集中插入每一条边,看是不是能让st 和 end 联通,那么现在的 加入的这条边的速度 - 第i条边的速度就是 当前枚举情况的最小差啦,,我们与ans 比较一下取小值就可以break,进入下一条边的枚举啦。因为速度都是按小到大排序的,次条边能让st 和 end联通,再加边,只会让速度差更大
上马:
//187MS 300K
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX 205
#define INF 1<<30
int N,M,Q;
struct Edge
{
int st,end,speed;
bool operator<(const Edge& E)const
{
return speed<E.speed;
}
} edge[MAX*5];
int father[MAX];
int find(int x)
{
if(x != father[x])
{
father[x] = find(father[x]);
}
return father[x];
}
int krustra(int st,int end)
{
int ans = INF;
//枚举
for(int i = 0; i < M; i ++)
{
int j;
for(j = 1; j <= N; j ++) father[j] = j;
for(j = i; j < M; j ++)
{
father[find(edge[j].st)] = find(edge[j].end);
//经过第i到第j条边的加入,我们可以使得st 和end 点联通
//并且我们早已经按速度排序,那么差值就是下面的
if(find(st) == find(end))
{
int pre = edge[j].speed - edge[i].speed;
if(ans > pre) ans = pre;
break;
}
}
//这里表示,从第i第M条边,都不能让st 和end 联通,那么可以break
if(j == M)
{
break;
}
}
return ans;
}
int main()
{
while(cin >> N >> M)
{
for(int i = 0; i < M ; i ++)
{
cin >> edge[i].st >> edge[i].end >> edge[i].speed;
}
sort(edge,edge+M);
int ans;
int st,end;
cin >> Q;
while (Q--)
{
cin >> st >> end;
ans = krustra(st,end);
if(ans == INF) cout << "-1" <<endl;
else cout << ans <<endl;
}
}
return 0;
}
个人愚昧观点,欢迎指正与讨论