zoukankan      html  css  js  c++  java
  • [HAOI2006]旅行

    题目:BZOJ1050、codevs1001、洛谷P2502。

    题目大意:见BZOJ的题目描述。

    解题思路:首先对所有的边按权值排序,然后枚举最小边i,对i~m的所有边,一条一条加进去,当s和t连通时(并查集维护)结束加边并判断最大边和最小边i的比值是否比当前答案较小,如果是则更新。最后得出的即为答案。如果s和t无法连通输出“IMPOSSIBLE”即可。时间复杂度$O(m^2)$。

    C++ Code:

    #include<algorithm>
    #include<cstdio>
    using namespace std;
    int n,m,s,t;
    struct Edges{
    	int from,to,dis;
    	bool operator <(const Edges&rhs)const{return dis<rhs.dis;}
    }e[5050];
    int fa[505];
    int dad(int x){return (x==fa[x])?(x):(fa[x]=dad(fa[x]));}
    int gcd(int x,int y){
    	if(x%y==0)return y;
    	return gcd(y,x%y);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;++i)
    	scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].dis);
    	scanf("%d%d",&s,&t);
    	sort(e+1,e+1+m);
    	int mx=0,mn=2000000000;
    	for(int i=1,j;i<=m;++i){
    		if(e[i].dis==e[i-1].dis)continue;
    		for(j=1;j<=n;++j)fa[j]=j;
    		bool flag=false;
    		for(j=i;j<=m;++j){
    			int a=dad(e[j].from),b=dad(e[j].to);
    			if(a!=b)fa[b]=a;
    			if(flag=(dad(s)==dad(t)))break;
    		}
    		if(flag&&(mn>mx||(double)mx/(double)mn>(double)e[j].dis/(double)e[i].dis))mx=e[j].dis,mn=e[i].dis;
    	}
    	if(mn>mx)puts("IMPOSSIBLE");else
    	if(!(mx%mn))printf("%d
    ",mx/mn);else{
    		int l=gcd(mx,mn);
    		printf("%d/%d
    ",mx/l,mn/l);
    	}
    	return 0;
    }
    

    注意代码第23行的优化。为什么可以这么优化呢?因为这条边与上一条边权值相同,在上一条边作最小边时,这条边已经被加进去过了,所以得到的答案不可能更优,或者是直接连通,比值为1,也不可能更优。所以可以这么优化。

    这是在BZOJ中优化前和优化后的对比(上为优化后):

     

     可以看到效果挺好的。

  • 相关阅读:
    关于负数补码的求解
    二维数组的行列指针
    复杂类型的解读
    单斜杠''的思考
    HTML 文本格式化实例--常用的标签
    P1 基础知识以及客户截面 【B站 SolidWorks2014教学视频 共计20讲】
    SolidWorks 2-5 草图的绘制
    SolidWorks 2-4 草图简介
    SolidWorks 模型创建的一般过程 2019年2月25日
    P3 3.HTML&CSS基础_HTML简介 (24'22")---------- 高质量HTML与CSS基础(共103讲)
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7281581.html
Copyright © 2011-2022 走看看