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中优化前和优化后的对比(上为优化后):

     

     可以看到效果挺好的。

  • 相关阅读:
    luogu P3239 [HNOI2015]亚瑟王
    android之软件键盘
    Eclipse输入智能提示设置
    防止反编译
    二进制数据读写
    数据类型转换
    类对象的读写文件
    Eclipse 快捷键
    修改IP
    Android eclipse 运行项目设置程序默认安装到SD卡
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7281581.html
Copyright © 2011-2022 走看看