题目描述
D 星有许多城市, 城市之间通过一种奇怪的高速公路连接, 每条高速公路 都对行驶在上面的汽车限制了固定的速度( 必须以这个速度行驶, 且汽车的提 速和减速是瞬间完成的) , 同时 D 星人对汽车的“舒适度” 有特殊要求, 即乘 车过程中最高速度与最低速度的差越小越舒服 , 但 D 星人对时间却没有很高的 要求。 请编程找出最舒适的行车路线。 (高速公路是双向的) 。
输入
第一行有 2 个正整数 n(2<=n<=200)和m(1<=m<=1000),表示有 n 个城市和 m 条高速公路, 城市从 1 到 n 编号。 接 下 来 的 m 行 , 每 行 三 个 正 整 数 S,E,K(1<=S,E<=n,S≠E,1<=K<=1000000) ,表示从 S 到 E 有一条限速为 K 的高速公路。
接下来一行是一个正整数 Q( 1<=Q<=10),表示需要寻找的行车线路条数。
接下来 Q 行每行有 2 个正整数 A,B(1<=A,B<=n,A≠B), 分别表示寻路的起点和终点。
输出
输出 Q 行,每行一个整数, 表示相应舒适度最好的线路的最高速与最低速之差。如果从起点不能到达终点,那么输出“ -1” ( 不包括双引号)。
样例输入
4 4
1 2 2
2 3 4
1 4 1
3 4 2
2
1 3
1 2
样例输出
1
0
提示
【数据范围】
30%的数据保证 2<=n<=50,1<=m<=100,1<=K<=100
50%的数据保证 2<=n<=100,1<=m<=500,1<=K<=100000
100%的数据保证 2<=n<=200,1<=m<=1000,1<=K<=1000000
Solution
初中题感觉没什么好方法阿。。。直接二分最小差,再枚举最小边,然后spfa判断能否到达终点。
复杂度最坏有nm∗m∗20,40亿。。。但考虑实际情况,实际上还是很快的。
怎么说呢,还是道水题吧
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll unsigned long long
using namespace std;
int n,m,tot,x,y,z,u,v,q,st,ed;
int head[205],Next[2005],to[2005],len[2005];
int f[205],vis[205],g[200005];
struct ty
{
int x,y,z;
}p[1005];
int get(int x)
{
if(f[x]==x) return f[x]; else return f[x]=get(f[x]);
}
void add(int x,int y,int z)
{
tot++;
Next[tot]=head[x];
to[tot]=y;
len[tot]=z;
head[x]=tot;
}
int check(int delta)
{
for(int i=1;i<=m;i++)
{
int limit=p[i].z;
int t=0,w=1;
for(int j=1;j<=n;j++) vis[j]=0;
g[1]=st,vis[st]=1;
while(t<w)
{
t++;
x=g[t];
if(x==ed) return 1;
for(int j=head[x];j!=-1;j=Next[j])
{
y=to[j],z=len[j];
if(z>=limit&&z<=limit+delta)
{
if(vis[y]==0)
{
w++;
g[w]=y;
vis[y]=1;
}
}
}
}
}
return 0;
}
int erfen(int l,int r)
{
if(l>r) return l;
int mid=(l+r)/2;
if(check(mid)) return erfen(l,mid-1); else return erfen(mid+1,r);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) head[i]=-1,f[i]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
add(p[i].x,p[i].y,p[i].z);
add(p[i].y,p[i].x,p[i].z);
u=get(p[i].x);
v=get(p[i].y);
f[v]=u;
}
cin>>q;
for(int i=1;i<=q;i++)
{
cin>>st>>ed;
if(get(st)!=get(ed)) cout<<"-1"<<endl; else cout<<erfen(0,1e6)<<endl;
}
return 0;
}