• 【bzoj1050】[HAOI2006]旅行comf


    1050: [HAOI2006]旅行comf

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2813  Solved: 1534
    [Submit][Status][Discuss]

    Description

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

    Input

      第一行包含两个正整数,N和M。下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向
    公路,车辆必须以速度v在该公路上行驶。最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速
    度比最小的路径。s和t不可能相同。
    1<N<=500,1<=x,y<=N,0<v<30000,0<M<=5000

    Output

      如果景点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
     
     
     
    【题解】
    这道题很有意思,具体算法流程如下:
    1.边按权值排序,标号1~m
    2.初始化一个枚举起点sta=1
    3.初始化并查集
    4.从sta开始顺推,利用并查集加边,直到s与t连通
    5.记录当前边编号为r
    6.初始化并查集
    7.从r逆推,利用并查集加边,直到s与t连通
    8.得到当前边编号,记为l
    9.[l,r]是一组比较优的可行解,更新答案
    10.枚举起点sta变为l+1,返回第3步继续执行
     
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<ctime>
     7 #include<algorithm>
     8 using namespace std;
     9 struct node{int u,v,w;bool operator<(const node c)const{return w<c.w;}}e[5010];
    10 int n,m,s,t,x,start=1,ansmx=1,ansmn,mx,mn,f[510];
    11 inline int read()
    12 {
    13     int x=0,f=1;  char ch=getchar();
    14     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
    15     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
    16     return x*f;
    17 }
    18 void pre() {for(int i=1;i<=n;i++)  f[i]=i;}
    19 int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    20 int gcd(int a,int b){return b? gcd(b,a%b):a;}
    21 int main()
    22 {
    23     //freopen("cin.in","r",stdin);
    24     //freopen("cout.out","w",stdout);
    25     n=read();  m=read();
    26     for(int i=1;i<=m;i++){e[i].u=read();e[i].v=read();e[i].w=read();}
    27     sort(e+1,e+m+1);
    28     s=read(),t=read();
    29     while(start<=m)
    30     {
    31         mx=-1;  mn=-1;
    32         pre();
    33         for(x=start;x<=m;x++)
    34         {
    35             int u=find(e[x].u),v=find(e[x].v);
    36             f[u]=v;
    37             if(find(s)==find(t))  {mx=e[x].w;  break;}
    38         }
    39         if(mx==-1)
    40         {
    41             if(!ansmn)  {printf("IMPOSSIBLE
    ");  return 0;}
    42             else break;
    43         }
    44         pre();
    45         for(;x>0;x--)
    46         {
    47             int u=find(e[x].u),v=find(e[x].v);
    48             f[u]=v;
    49             if(find(s)==find(t))  {mn=e[x].w;  break;}
    50         }
    51         start=x+1;
    52         if(mn==-1)
    53         {
    54             if(!ansmn)  {printf("IMPOSSIBLE
    ");  return 0;}
    55             else break;
    56         }
    57         int r=gcd(mx,mn);  
    58         mx/=r;  mn/=r;
    59         if(mx*ansmn<ansmx*mn)  {ansmn=mn;  ansmx=mx;}
    60     }
    61     if(ansmn==1)  printf("%d",ansmx);
    62     else printf("%d/%d",ansmx,ansmn);
    63     return 0;
    64 }
  • 相关阅读:
    ssm之spring+springmvc+mybatis整合初探
    mybatis缓存之整合第三方缓存工具ehcache
    mybatis缓存之二级缓存
    mybatis缓存之一级缓存
    mybatis动态sql之利用sql标签抽取可重用的sql片段
    mybatis动态sql之bind标签
    mybatis动态sql之内置参数_parameter和_databaseId
    mybatis动态sql之使用foreach进行批量插入的两种方式
    mybatis动态sql之foreach补充(三)
    Visitor Pattern
  • 原文地址:https://www.cnblogs.com/chty/p/5950877.html
Copyright © 2020-2023  润新知