[HAOI2006] 旅行

【题目描述】

 

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”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。

 

 

 

【样例输入1】

4 2
1 2 1
3 4 2
1 4


【样例输出1】

IMPOSSIBLE

【样例输入2】

3 3 1 2 10 1 2 5 2 3 8 1 3

【样例输出2】

5/4

【样例输入3】

3 2
1 2 2
2 3 4
1 3

【样例输出3】

2
0<N<=500;0<M<=5000,v<=30000;


题解:
将边从小到大排序,枚举最小速度,然后选大于最小速度的边使s,t联通,统计答案即可
 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 using namespace std;
 8 const int M=5005;
 9 int gi(){
10     int str=0;char ch=getchar();
11     while(ch>'9' || ch<'0')ch=getchar();
12     while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
13     return str;
14 }
15 struct node{
16     int x,y,dis;
17     bool operator <(const node &pp)const{
18         return dis<pp.dis;
19     }
20 }e[M];
21 int n,m,fa[505];
22 int find(int x){
23     return x==fa[x]?x:fa[x]=find(fa[x]);
24 }
25 int fm=100000,fz=1,s,t;
26 bool check(int sta){
27     int x,y,mx=e[sta].dis;
28     for(int i=1;i<=n;i++)fa[i]=i;
29     fa[find(e[sta].y)]=find(e[sta].x);
30     for(int i=sta+1;i<=m;i++){
31         x=e[i].x;y=e[i].y;
32         if(find(s)==find(t))break;
33         if(find(x)==find(y))continue;
34         mx=e[i].dis;fa[find(y)]=find(x);
35     }
36     if(find(s)!=find(t))return false;
37     if(mx*fz<fm*e[sta].dis){
38         fz=e[sta].dis;fm=mx;
39     }
40     return true;
41 }
42 int gcd(int x,int y){return x%y?gcd(y,x%y):y;}
43 void work()
44 {
45     n=gi();m=gi();
46     for(int i=1;i<=m;i++)
47         e[i].x=gi(),e[i].y=gi(),e[i].dis=gi();
48     sort(e+1,e+m+1);
49     s=gi();t=gi();
50     for(int i=1;i<=m;i++){
51         if(!check(i))break;
52     }
53     if(fm==100000){
54         printf("IMPOSSIBLE\n");
55         return ;
56     }
57     if(!(fm%fz)){
58         printf("%d\n",fm/fz);
59         return ;
60     }
61     int ops=gcd(fm,fz);
62     printf("%d/%d\n",fm/ops,fz/ops);
63 }
64 int main()
65 {
66     freopen("comf.in","r",stdin);
67     freopen("comf.out","w",stdout);
68     work();
69     return 0;
70 }
 
 

 

 

转载于:https://www.cnblogs.com/Yuzao/p/7207713.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值