题解 洛谷 P2502 【[HAOI2006]旅行】
给出一张无向图,给出一个s,t使得这条路上最大值和最小值的比值最最小,并且输出既约分数(即最简分数)
并查集做法:
枚举最小值,找最大值。每次加入直到可以联通,这时比较ans大小,能更新则更新。
ans更新时是分数比大小,直接两个分子乘上互相的分母即可。
Code:
#include <bits/stdc++.h>
using namespace std;
int f[1000005],n,m,x,y,z,s,t,ans1=30001,ans2=1;bool flag=false;
struct edge{
int u,v,w;
} e[100005];
// 结构体存图,u,v:两条边,w:权值
inline void init(int n){for(int i=1;i<=n;++i)f[i]=i;}//并查集初始化
inline int find(int x){return f[x]==x?x:f[x]=find(f[x]);}//查询操作
inline bool cmp(edge x,edge y){return x.w<y.w;}//cmp比较函数,按照权值大小进行升序排序
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&z);
e[i].u=x,e[i].v=y,e[i].w=z;
//输入图
}
scanf("%d%d",&s,&t);
sort(e+1,e+1+m,cmp);
//排序
for(int min_index=1;min_index<=m;++min_index){
//枚举最小值下标
init(n);flag=false;//flag代表每次是否更新ans
int max_index=min_index;
for(max_index=min_index;max_index<=m;++max_index){
//最大值下标
int p=find(e[max_index].u),q=find(e[max_index].v);
if(p!=q)f[p]=q;
// 将两个元素合并,效果等于奆佬们常写的merge
if(find(s)==find(t))
{flag=true;break;}
//假如两个点联通,又因为升序排了权值,所以此时的解必然是当前min_index和max_index里的最小值
}
if(flag)if(ans1*e[min_index].w>ans2*e[max_index].w)ans1=e[max_index].w,ans2=e[min_index].w;
// 分数比大小
}
if(ans1==30001)puts("IMPOSSIBLE");
// 假如ans没有被更新,则没有联通,输出"IMPOSSIBLE"
else{
int com=__gcd(ans1,ans2);
ans1/=com,ans2/=com;
// 即约分数,化简分数
if(ans2==1)printf("%d\n",ans1);
// 若分母为1,直接输出分子
else printf("%d/%d\n",ans1,ans2);
}
return 0;
}
posted on 2021-01-04 22:14 ExcaliburGod 阅读(66) 评论(0) 收藏 举报
浙公网安备 33010602011771号