XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超级空中漫游结构)进行交流,每条SARS都对行驶在上面的Flycar限制了固定的Speed,同时XX星人对 Flycar的“舒适度”有特殊要求,即乘坐过程中最高速度与最低速度的差越小乘坐越舒服 ,(理解为SARS的限速要求,flycar必须瞬间提速/降速,痛苦呀 ),
但XX星人对时间却没那么多要求。要你找出一条城市间的最舒适的路径。(SARS是双向的)。
Input
输入包括多个测试实例,每个实例包括:
第一行有2个正整数n (1<n<=200)和m (m<=1000),表示有N个城市和M条SARS。
接下来的行是三个正整数StartCity,EndCity,speed,表示从表面上看StartCity到EndCity,限速为speedSARS。speed<=1000000
然后是一个正整数Q(Q<11),表示寻路的个数。
接下来Q行每行有2个正整数Start,End, 表示寻路的起终点。Output每个寻路要求打印一行,仅输出一个非负整数表示最佳路线的舒适度最高速与最低速的差。如果起点和终点不能到达,那么输出-1。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
算法
这道题最大的一条最小 最小的最大
1.二分 2.生成树
拿到应该先想二分
但是二分感觉不行
所以考虑生成树
因为排序后的序列是单调递增的
所以每次选择一条边 从它开始枚举 跑生成树
最后 当 起点和终点都在 集合里面时 结束
用最后加的边减去 当前枚举的边
正确性证明
如果当前的边不在最小生成树里面
那么生成树里面的边都比当前的边大
所以当我继续枚举后 差值越变越小
code:
// #include<bits/stdc++.h> using namespace std; #define maxnn 100000 int n,m; int Q; int tot; int f[maxnn]; struct node { int en,le; int sta; }tree[maxnn]; void add(int a,int b,int c) { tree[++tot].en=b; tree[tot].sta=a; tree[tot].le=c; } bool cmp(node a,node b) { return a.le<b.le; } int gf(int v) { return f[v]==v? v: f[v]=gf(f[v]); } void kruskal(int a,int b) { int ans=1000000000; for(int i=1;i<=tot;i++) { for(int z=1;z<=n;z++) { f[z]=z; } for(int j=i;j<=tot;j++) if(gf(tree[j].sta)!=gf(tree[j].en)) { f[gf(tree[j].sta)]=gf(tree[j].en); if(gf(a)==gf(b)) { ans=min(ans,tree[j].le-tree[i].le); break; } } } if(ans==1000000000) cout<<-1<<endl; else cout<<ans<<endl; } int main() { int a,b,c; int st,e; while(cin>>n>>m) { tot=0; for(int i=1;i<=m;i++) { cin>>a>>b>>c; add(a,b,c); add(b,a,c); } sort(tree+1,tree+1+tot,cmp); cin>>Q; for(int i=1;i<=Q;i++) { for(int i=1;i<=n;i++) { f[i]=i; } cin>>st>>e; kruskal(st,e); } } }