极品飞车(并查集+枚举)
Posted YJSheep
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了极品飞车(并查集+枚举)相关的知识,希望对你有一定的参考价值。
极品飞车(并查集+枚举)
Hecy被FC星人劫持了!
“长的帅也是一种罪过吗?”,Hecy问劫持他的生物,结果被暴打。唉,原来Hecy被劫持的原因是FC星人看中了他的编程才能(“我真的长的不帅吗?”Hecy不死心地问另一个生物,结果再次被暴打)。
FC星有许多城市,某些城市之间无法直接到达,但某些城市之间可以通过一种奇怪的高速公路SARS(Super Air Roam Structure 超级空中漫游结构)进行人员或物资的交流运输。在SARS上有且仅有一种“车”可以行驶,那就是传说中的极品飞车Flycar。东东们就是乘坐着Flycar在SARS上运动的。与地球相似地,每条SARS都对行驶在他上面的Flycars有限速要求——不同的是这既不是限最高速,也不是限最低速,而是限固定速,也就是说Flycars必须以所限速度行驶,否则就要被TS(Traffic System)来一次ts(tiger strike虎击)——这可不是好玩的!
同时FC星人对flycar的“舒适度”也有特殊的要求。他们认为乘坐一次flycar过程中,flycar达到的最高速与最低速之间的差越小,本次乘坐越舒适(可以理解,因为SARS的限速要求,flycar都必须瞬间提/降速,痛苦啊)——FC星人对时间却没那么多要求。
因此Hecy的任务就明确了:为FC星上几乎垄断了flycar市场的全星通用汽车公司(CC)设计新一代自动寻路flycar,使得该flycar能自动寻找两城市间最舒适的到达路径。
任务
对于给定的公路网以及两个城市s、t,求出从s到t的最舒适路径。
输入
输入数据的第一行两个正整数n、m(1<=n〈=200,1〈=m<=1000),n、m分别表示城市数和公路数。
第二行是两个正整数s、t,表示初始城市和目标城市。
接下来的n行每行三个正整数i、j、num(num〈=1000000),表示城市I,j之间有一条道路,该路的限时为num.
输出
输出数据的第一行为最舒适值。
第二行依次输出最舒适路径上的城市。
注意:如果有多个数据满足问题的要求,只要输出一个即可。
样例输入
2 1
1 2
1 2 1
样例输出
0
1 2
解题报告
这一题和舒适的路径很像。主要要借助并查集。我们不妨把所有边按从小到大排序。并从小到达枚举边,将其作为最小边,依次按之后的边用并查集将点合并,直到起点与终点相连。这样,最高速度与最低速度的差就是所枚举的最小边与当前边的差。枚举出所有差,取最小值即可。这种解法与最小生成树有异曲同工之妙。
#include<queue> #include <algorithm> #include<cstdio> #include<cstring> #include<cmath> #define Pair pair<int,int> #define MAXN 1000+10 #define MAXM 600000+1 #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) using namespace std; int n,m,num,s,t,pre[MAXN],v[MAXM],as; int fa[MAXM]; struct Edge{ int dis,next,to,exi,from; }edge[MAXM]; bool cmp(Edge a,Edge b) { return a.dis<b.dis; } int find(int x) { if(fa[x]!=x) fa[x]=find(fa[x]); return fa[x]; } void un(int x,int y) { fa[y]=x; } void work(int s,int t) { int mind=99999999,flag=0; for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) fa[j]=j; int minn=edge[i].dis,maxn=0; for(int j=i;j<=m;j++) { int a=find(edge[j].from),b=find(edge[j].to); if(a!=b) { un(a,b); maxn=edge[j].dis; if(find(s)==find(t)) { mind=min(mind,maxn-minn); flag=1; break; } } } } if(mind!=99999999) printf("%d\n",mind); else printf("-1\n",mind); } int main() { freopen("flycar.in","r",stdin); freopen("flycar.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].dis); } sort(edge+1,edge+1+m,cmp); scanf("%d",&as); for(int i=1;i<=as;i++) { scanf("%d%d",&s,&t); work(s,t); } return 0; }
以上是关于极品飞车(并查集+枚举)的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2912 - Rochambeau - [暴力枚举+带权并查集]
USACO环绕岛屿Surround the Islands 并查集 枚举暴力