暴力摩托
Description
N个站,之间连了M条双向的通路!但每条路都规定了一个速度的限制值,在这条路上必须以这个速度前进!所以在前进的时候要调整速度,现决定尽量使调整的幅度小一些,也就是使走过的路的速度最大值与最小值之差最小!
Input
第一行有2个正整数N , M , 分别表示站点数,路径数.
接下来M行,每行有3个正整数 X, Y, V表示X, Y之间有一条路,其Speed值是V。
再接下来是数K, 表示任务数,
下面K行,每行有一对正整数P,Q ,表示一个任务从P到Q.
(1<=n<=200, 1<=m<=1000, 1<=K<=10)
Output
对于每一个任务输出一行,仅一个数,即最大速度与最小速度之差。
Sample Input
4 4
1 2 2
2 3 4
1 4 1
3 4 2
2
1 3
1 2
Sample Output
1
0
思路
题目给出点数n,边数m,x与y之间有长度为v的双向边。使从a走到b的路径中(max v-min v)最小。
把边按v升序排列,循环枚举i:1-m,再嵌套枚举j:i-m,认为这条路径是由第i条边到第j条边组成的。每次加入一条边,那么这条边的2个端点就为同一父亲,之后检查a,b是否为同一个父亲,如果是,那么a,b就连通了,(max v-min v)=(car[j].v-car[i].v),ans取min;否则继续加边。
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,k,maxx,minn,a,b,t1,t2,d[201],ans,kk;
struct note//结构体
{
int x,y,v;
}car[1010];
bool cmp(note x,note y)//结构体按v升序排列
{
return x.v<y.v;
}
int find(int x)//找父亲+路径压缩
{
if(d[x]!=x)
d[x]=find(d[x]);
return d[x];
}
void check()
{
ans=2147483647;
for(int i=1;i<=m;i++)
{
for(int i=1;i<=200;i++)
d[i]=i;//注意:每次都要重置
for(int j=i;j<=m;j++)
{
t1=find(car[j].x);
t2=find(car[j].y);
if(t1!=t2)
d[t1]=t2;
if(find(a)==find(b))//a,b连通了
{
ans=min(ans,(car[j].v-car[i].v));
break;
}
}
}
printf("%d\n",ans);
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d %d %d",&car[i].x,&car[i].y,&car[i].v);
sort(car+1,car+1+m,cmp);//排序
scanf("%d",&k);
for(kk=1;kk<=k;kk++)
{
scanf("%d %d",&a,&b);
check();
}
return 0;
}
后
每次从一个新的i开始加边之前,要把所有点的父亲都设为自己。
通过并查集,我们1.可以连通两点。2.判断是否连通。