HDU1598
题意:找两点是否连通,如果不连通,就输出-1
如果连通,找出连接两点之间的路线中,速度的最大和最小差值最小的路径,并输出差值。
题解:暴力枚举+最小生成树
首先题目给出时间不重要~
先把边的速度从小到大sort一遍
所以枚举速度最小的边,然后找到速度最大的边。一条边一条边去找,如果两点联通了,那么最大边就找到了,直接break。可以起到绕来绕去,想去最小边,再去最大边,再去终点。反正时间不重要。
代码:
#include <bits/stdc++.h>
using namespace std;
int const inf = 0x7f7f7f7f;
int const N = 200 + 10;
int const M = 1000 + 10;
int n,m,q,fa[N];
struct Edge
{
int u,v,s;
}p[M];
bool cmp(Edge a,Edge b){
return a.s < b.s;
}
void Init(){
for(int i=1;i<=n;i++) fa[i] = i;
}
int find(int x){
return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
int kruskal(int e,int x,int y){ //求x,y两点之间的最小速度
Init();
int maxd = -inf,mind = inf;
bool flag = false;
for(int i=e;i<m;i++){
if(find(x) == find(y)){ //如果连通了
flag = true;
break;
}
int fx = find(p[i].u), fy = find(p[i].v);
if(fx != fy){
maxd = max(maxd,p[i].s);
mind = min(mind,p[i].s); //这里mind起始不需要,因为第一条边一定是速度最小的边
fa[fx] = fy;
}
}
if(flag) return maxd - mind;
else return -1;
}
int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=0;i<m;i++){
int x,y,s;
scanf("%d%d%d",&x,&y,&s);
p[i] = (Edge){x,y,s};
}
sort(p,p+m,cmp);
scanf("%d",&q);
for(int i=0;i<q;i++){
int x,y;
scanf("%d%d",&x,&y);
int ans = inf;
for(int j=0;j<m;j++){
int tmp = kruskal(j,x,y);
if(tmp != -1) ans = min(ans,tmp);
}
if(ans == inf) printf("-1\n");
else printf("%d\n",ans);
}
}
}