Luogu P2502 [HAOI2006] Travel - Problem Solving

The main idea of ​​the topic portal
title:
There are n points and m edges, and each edge has a weight. In all paths between two points, what is the smallest ratio of the largest weight to the smallest weight.


Thinking process:
The question asks about the ratio of the largest weight to the smallest weight. It is difficult to get the ratio directly. We might as well fix the edge with the smallest weight first, and then enumerate the edge with the largest weight, so that as long as the weight is the largest The weight of the edge should be as small as possible. Thinking of this, the algorithm is ready to come out. Similar to the minimum spanning tree (Kruskal), we sort all the edges by weight from small to large, enumerate the edges with the smallest weight from 1 to m, and use union search to maintain connectivity, when s and t When it is connected, break it and record the best answer.


Specific methods:
1. Sort all the edges by weight from small to large
2. Sweep the edges from front to back, and check the set to judge the connectivity, jump out of the loop when s and t are connected, and compare whether the answer is better, and the better is Record
3. Briefly discuss several situations when outputting the answer


Code:

#include <bits/stdc++.h>
using namespace std;

const int maxn=510,maxm=5100;
const double inf=20020816.0;
struct stu
{
    int x,y,dis;    
}road[maxm];
double ans=inf;
int ans2,ans1,n,m,s,t;
int fa[maxn];

bool cmp(stu t1,stu t2)
{
    return t1.dis<t2.dis;   
}

int find(int x)
{
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);   
}

int gcd(int x,int y)
{
    if(!y) return x;
    return gcd(y,x%y);
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) scanf("%d%d%d",&road[i].x,&road[i].y,&road[i].dis);
    scanf("%d%d",&s,&t);
    sort(road+1,road+1+m,cmp);
    for(int i=1;i<=m;i++)
    {
        if(road[i].dis==road[i-1].dis) continue;
        bool flag=0;
        int m1=road[i].dis,m2=road[i].dis;
        for(int j=1;j<=n;j++) fa[j]=j;
        for(int j=i;j<=m;j++)
        {   
            int p1=find(road[j].x),p2=find(road[j].y);
            if(p1!=p2) { fa[p1]=p2;m2=road[j].dis; }
            if(find(s)==find(t))
            {
                flag=1;
                break;
            }
        }
        if(!flag) break;
        double nowans=((double)m2)/((double)m1);
        if(nowans<ans) { ans=nowans;ans1=m1;ans2=m2; }
    }
    if(ans==inf) { printf("IMPOSSIBLE\n");return 0; }
    if(ans-(int)ans==0) { printf("%d\n",(int)ans);return 0; }
    int kk=gcd(ans1,ans2);
    ans1/=kk;ans2/=kk;
    printf("%d/%d\n",ans2,ans1);
    return 0;   
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324871858&siteId=291194637