zoukankan      html  css  js  c++  java
  • BZOJ1050 [HAOI2006]旅行comf[并查集判图连通性]

    Description

    给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T,求
    一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个
    比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。

    体现了并查集实际作用的一道题,也就是判图连通性。几句总结:

    最小化或最大化一个分数时通常可以二分,但是也可以去设法最大or最小化分子分母。二分不好check的话就可以尝试后者。


    据说二分带点优化其实是可以的,然而我不会。根据上面那则提示,因为最大边和最小边无法同时分别最小和最大化,所以可以先固定分母(最小边)。然后要求分子尽可能小。就是说找大于最小边的一些边让s到t连通,最小化那个最大边。那么对于最小的最大边,只要从最小边开始从小到大不停加边,直到s与t连通时立即停止即可,找到的一定是最小的最大边,正确性很容易证(最小的可行解之前的所有边都无法使其连通,而当前为第一个可行解,即最小)。于是枚举最小边并查集维护连通性就行,$O(N^{2}α(N))$稍有点卡,但是能过。可以把除法比较转换成乘法比较加一点速。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<queue>
     7 #define dbg(x) cerr<<#x<<" = "<<x<<endl
     8 #define ddbg(x,y) cerr<<#x<<" = "<<x<<"   "<<#y<<" = "<<y<<endl
     9 using namespace std;
    10 typedef long long ll;
    11 typedef double db;
    12 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
    13 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
    14 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    15 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    16 template<typename T>inline T read(T&x){
    17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    19 }
    20 const int N=5000+7;
    21 struct thx{
    22     int u,v,w;
    23     inline bool operator <(const thx&orz)const{
    24         return w<orz.w;
    25     }
    26 }e[N];
    27 int fa[N],n,m,s,t,p=300000,q=1;
    28 inline int Get(int x){return fa[x]^x?fa[x]=Get(fa[x]):x;}
    29 inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
    30 
    31 int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
    32     read(n),read(m);
    33     for(register int i=1;i<=m;++i)read(e[i].u),read(e[i].v),read(e[i].w);
    34     sort(e+1,e+m+1);read(s),read(t);
    35     for(register int i=1;i<=m;++i){
    36         int j;for(j=1;j<=n;++j)fa[j]=j;
    37         for(j=i;j<=m;++j){
    38             fa[Get(e[j].u)]=Get(e[j].v);
    39             if(Get(s)==Get(t))break;
    40         }
    41         if(Get(s)==Get(t))if(p*e[i].w>q*e[j].w)p=e[j].w,q=e[i].w;
    42     }
    43     if(p>30000)printf("IMPOSSIBLE
    ");
    44     else p%q==0?printf("%d",p/q):printf("%d/%d
    ",p/gcd(p,q),q/gcd(p,q));
    45     return 0;
    46 }
  • 相关阅读:
    共创力董事长杨学明先生受邀参加CED智慧大会!
    杨学明老师为华宇金信(北京)软件有限公司提供为期两天的内训服务!
    《互联网敏捷测试管理实践》课程大纲 2018.12.15~16 (上海)
    共创力咨询杨学明老师为国电南瑞提供两天的内训服务!
    《软件测试管理》深圳公开课预告 2018.11.23~24 中南海滨大酒店
    软件测试管理的十大挑战
    对于开发人员修改代码引发新问题的处理措施
    热烈庆祝杨学明老师为上海某著名金融互联网公司提供两天的内训服务!
    《高效的互联网研发项目管理》课程大纲
    《软件测试管理》北京公开课预告 2018.9.28~29
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10644206.html
Copyright © 2011-2022 走看看