题目描述
Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。Z小镇附近共有N个景点(编号为1,2,3,…,N),这些景点被M条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路。也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。速度变化太快使得游客们很不舒服,因此从一个景点前往另一个景点的时候,大家都希望选择行使过程中最大速度和最小速度的比尽可能小的路线,也就是所谓最舒适的路线。
输入格式
第一行包含两个正整数,N和M。
接下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路,车辆必须以速度v在该公路上行驶。
最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。
输出格式
如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。
主要思路:
这个题主要是枚举+生成树,我们先将边存下来,将其按照从大到小排序,然后从大到小每次固定一条边,然后枚举依次小于该固定的边的以后的边,判断IMPOSSIBLE的条件显然是无论如何枚举都无法构成一棵生成树,当每次选择的边数等于n-1,此时该情况的值即为一开始固定的边的边权/最后枚举到的这条边的权值,然后我们把它们都存下来,根据x/y由小到大排序,至于约分,只需要求出两者的gcd,让分子与分母都除以gcd,若分母除以gcd后等于一,则说明该分数可以化简为整数,详见代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; #define maxn 30010 #define ll long long #define IL inline #define clear(a) memset(a,0,sizeof a) int n,m,star,en,tot,ansx,ansy,lazy; int fa[maxn]; struct edge{ int a,b,val; bool operator < (const edge & other)const{ return val>other.val; } }e[maxn]; struct node{ int x,y; bool operator < (const node & other)const{ return (double)((double)x/(double)y)<(double)((double)other.x/(double)other.y); } }num[maxn]; int findx(int x){ if(x==fa[x])return x; else return fa[x]=findx(fa[x]); } int gcd(int a,int b){ if(b==0)return a; else return gcd(b,a%b); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].val); scanf("%d%d",&star,&en); sort(e+1,e+m+1); for(int s=1;s<=m;s++){ for(int i=1;i<=n;i++)fa[i]=i; int f_x=findx(e[s].a),f_y=findx(e[s].b); fa[f_x]=f_y; if(findx(star)==findx(en)){ printf("1 "); return 0; } for(int i=s+1;i<=m;i++){ int fx=findx(e[i].a),fy=findx(e[i].b); if(fx!=fy){ fa[fx]=fy; if(findx(star)==findx(en)){ lazy=1; num[++tot].x=e[s].val; num[tot].y=e[i].val; break; } } } } if(lazy==0){ printf("IMPOSSIBLE "); return 0; } sort(num+1,num+tot+1); int g=gcd(num[1].x,num[1].y); if(num[1].y/g==1){ printf("%d",num[1].x/g); return 0; } else printf("%d/%d ",num[1].x/g,num[1].y/g); return 0; }