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

     

     可以看到效果挺好的。

  • 相关阅读:
    LeetCode Single Number
    Leetcode Populating Next Right Pointers in Each Node
    LeetCode Permutations
    Leetcode Sum Root to Leaf Numbers
    LeetCode Candy
    LeetCode Sort List
    LeetCode Remove Duplicates from Sorted List II
    LeetCode Remove Duplicates from Sorted List
    spring MVC HandlerInterceptorAdapter
    yum
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7281581.html
Copyright © 2011-2022 走看看