暴力摩托

Problem : 暴力摩托

Time Limit: 1 Sec Memory Limit: 128 MB

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

HINT

题目分析

1.题意

本题就是说让我们找一条路径从P到Q,是这条路上的最大速度限制与最小速度限制相差最小。
同样要运用到并查集。

2.分析

很明显我们要使最大速度限制尽可能的小,而最小速度限制尽可能的大。
那么我们每次在枚举的过程:
1.将题中给出的数据进行合并;
2.总是需要判断P,Q两点是否相连(即在并查集中,两者根一致),而且我们在路径压缩的同时也能够知道,两者的“父亲”也肯定是一样的。
3.最后退出循环,判断两者父亲节点是否相同,更新答案。
PS:注意排序!!!

代码:

#include <cstdio>
#include <climits>
#include <algorithm>
#pragma GCC optimize(2)
using namespace std;

int n,m,k;
int fa[201];
struct way
{
	int x,y,v; //x:出发点,y:目的点,v:速度
} s[1001];

int find(int x)
{
	return x==fa[x]? x:fa[x]=find(fa[x]);
	//路径压缩,将路上递归到的父亲节点指针顺带指向根节点
	//三目运算符更加简便
}

int solve(int P,int Q)
{
	int i,l,ans=INT_MAX;
	//注意循环里的数要定义在外,否则在判断时,循环变量只在循环里起作用
	//ans初始化
	for (i=1;i<=m;i++) //枚举最小速度
	{
		for (int j=1;j<=n;j++) fa[j]=j; //初始化
		for (l=i;l<=m;l++) //保证枚举到的最大速度一定不小于最小速度
						   //所以需要sort,便于循环枚举
		{
			int a=find(s[l].x),b=find(s[l].y); //取出两个点的根
			if (a!=b) fa[b]=a; //如若不在同一连通块,合并
			if (find(P)==find(Q)) break; //若P与Q在同一连通块,则退出
		}
		if (fa[P]==fa[Q]&&ans>s[l].v-s[i].v)
		//因为已经路径压缩,那么P和Q点的父亲一定为同一节点
		//同时注意,如果P和Q并没有相连,循环也会退出,所以需要判断
		//ans大于现所算出的答案才更新
			ans=s[l].v-s[i].v; //更新ans
	}
	return ans;
}

bool cmp(way a,way b)
{
	return a.v<b.v; //按速度大小排序
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
		scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].v);
	sort(s+1,s+m+1,cmp);
	//排序,注意按速度排序,后面会讲到
	int p,q;
	scanf("%d",&k);
	for (int i=0;i<k;i++)
	{
		scanf("%d%d",&p,&q);
		printf("%d\n",solve(p,q));
	}
	return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值