zoukankan      html  css  js  c++  java
  • codevs 1001 舒适的路线 WK

    题目描述 Description

    Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。
    Z小镇附近共有
    N(1<N≤500)个景点(编号为1,2,3,…,N),这些景点被M(0<M≤5000)条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路。也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。频繁的改变速度使得游客们很不舒服,因此大家从一个景点前往另一个景点的时候,都希望选择行使过程中最大速度和最小速度的比尽可能小的路线,也就是所谓最舒适的路线。

    输入描述 Input Description

    第一行包含两个正整数,N和M。
    接下来的M行每行包含三个正整数:x,y和v(1≤x,y≤N,0 最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。

    输出描述 Output Description

    如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。

    样例输入 Sample Input

    样例1
    4 2
    1 2 1
    3 4 2
    1 4

    样例2
    3 3
    1 2 10
    1 2 5
    2 3 8
    1 3

    样例3
    3 2
    1 2 2
    2 3 4
    1 3

    样例输出 Sample Output

    样例1
    IMPOSSIBLE

    样例2
    5/4

    样例3
    2

    数据范围及提示 Data Size & Hint

    N(1<N≤500)

    M(0<M≤5000)

    Vi在int范围内

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int n,m,j,ans1=0,ans2=0;
    struct dsl
    {
    	int f,t,w;
    } e[5001];
    int f[501];
    int getf(int a)  //并查集操作
    {
    	if(f[a]==a)
    		return a;
    	else
    		return a=getf(f[a]);
    }
    bool merge(int a,int b)//并查集操作
    {
    	int c=getf(a);
    	int d=getf(b);
    	if(c==d)return false;//不能够合并
    	f[c]=d;
    	return true;//合并成功
    }
    bool cmp(dsl a,dsl b)
    {
    	return a.w<b.w;
    }
    int gcd(int a,int b)
    {
    	return b==0?a:gcd(b,a%b);
    }
    int main()
    {
    	cin>>n>>m;
    	int F,T;
    	for(int i=1; i<=m; ++i)
    		cin>>e[i].f>>e[i].t>>e[i].w;
    	cin>>F>>T;
    	sort(&e[1],&e[m+1],cmp);    //对路径进行排序,以便克鲁斯卡尔
    	int w1,w2,cnt;
    	bool fl;
    	for(int i=1; i<=m; ++i)     //枚举从权值第i小的路径开始进行克鲁斯卡尔
    	{
    		for(int q=1; q<=n; ++q) //并查集不能够忘记预处理
    			f[q]=q;
    		j=i;
    		w1=e[i].w;              //因为已经排过了序,第一条一定是最短的
    		cnt=n-1;                //最小生成树要n-1条边
    		fl=false;               //返回是否成功标记
    		while(j<=m&&cnt)
    		{
    			if(merge(e[j].f,e[j].t))//如果合并成功,计数器减一
    				cnt--;
    			if(getf(T)==getf(F))    //如果目标点已经联通
    			{
    				fl=true;            //标记为成功
    				break;              //直接退出循环
    			}
    			j++;                    //枚举下一条边
    		}
    		if(!fl)break;               //如果当前已经无法使目标点联通,则接下来一定无法联通了,可以直接退出
    		w2=e[j].w;                  //当前最大的权值就是当前指向的边
    		if(ans1==0)                 //记录答案
    		{
    			ans1=w1;
    			ans2=w2;
    		}
    		else
    			if(w2/(w1*1.0)<ans2/(ans1*1.0))
    			{
    				ans1=w1;
    				ans2=w2;
    			}
    	}
    //输出部分
    	if(ans1==ans2&&ans1==0)
    		cout<<"IMPOSSIBLE"<<endl;
    	else
    	{
    		int k=gcd(ans2,ans1);
    		if(k==ans1)
    			cout<<ans2/ans1<<endl;
    		else
    			cout<<ans2/k<<'/'<<ans1/k<<endl;
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    工欲善其事,必先利其器
    年度总结
    人脸解锁从底层到上层(一)
    Hexo NexT 主题添加评论和文章阅读量
    摄影历程-第一章
    西藏之旅
    软件测试和评估
    WordCount优化
    WordCount编码与测试
    值得深入思考的五个问题
  • 原文地址:https://www.cnblogs.com/lyqlyq/p/7202640.html
Copyright © 2011-2022 走看看