旅行

link

题意是给定一个无向图,边有边权。求解一条连接指定两个点的路径使得路径上最大边和最小边的比值最小。

很明显发现边数很小,甚至可以 \(O(M^2)\) 跑过去。于是考虑每次枚举最短边,然后递增地枚举比它长的边一直到指定的两个点联通为止。考场上脑抽了写了个dfs,为了实现它还在删边上耗费了点时间。题解说可以用并查集维护,豁然开朗维生素B。题解区还有生成树的做法但没去细看,毕竟前面的做法已经挺优秀了。

#include<bits/stdc++.h>
//#define zczc
#define ll long long
const int N=510;
const int M=5010;
const int maxn=1e9;
using namespace std;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}

int m,n,s,tt;

struct node{
	int a,b,c,i1,i2;
}a[M];
inline bool cmp(node s1,node s2){
	return s1.c<s2.c;
}
struct edge{
	int t,next;
}e[M<<1];
int esum,head[N];
inline void add(int fr,int to){
	e[++esum]=(edge){to,head[fr]};head[fr]=esum;
}

void del(int wh,int id){
	if(head[wh]==id){head[wh]=e[id].next;return;}
	for(int i=head[wh],last;i;i=e[i].next){
		if(i==id){e[last].next=e[i].next;return;}
		last=i;
	}
}
void dele(int wh){
	del(a[wh].a,a[wh].i1);
	del(a[wh].b,a[wh].i2);
	return;
}

int ti,t[N];
void dfs(int wh){
	//printf("now:%d\n",wh);
	if(wh==tt)return;
	for(int i=head[wh],th;i;i=e[i].next){
		if(t[th=e[i].t]==ti)continue;
		t[th]=ti;dfs(th);
	}
}
inline bool check(){
	ti++;t[s]=ti;
	dfs(s);
	return t[tt]==ti;
}
void adde(int wh){
	add(a[wh].a,a[wh].b);
	a[wh].i1=esum;
	add(a[wh].b,a[wh].a);
	a[wh].i2=esum;
	return;
}

inline ll gcd(ll s1,ll s2){
	return s2==0?s1:gcd(s2,s1%s2);
}

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);read(n);
	for(int i=1;i<=n;i++){
		read(a[i].a);read(a[i].b);read(a[i].c);
	}
	read(s);read(tt);
	sort(a+1,a+n+1,cmp);
	
	ll aa=1,ab=maxn;
	
	int l=1,r=0;
	for(;l<=n;l++){
		if(l!=1)dele(l-1);
		while(!check()&&r<n)adde(++r);
		if(!check())break;
		ll na=a[l].c,nb=a[r].c;
		//printf("%d %d %d\n",check(),l,r);
		//printf("%lld %lld %lld %lld\n",aa,ab,na,nb);
		if(ab*na>aa*nb)aa=na,ab=nb;
		
	}
	ll g=gcd(aa,ab);
	aa/=g,ab/=g;
	if(ab==maxn){
		printf("IMPOSSIBLE\n");
		return 0;
	}
	if(aa==1)printf("%lld\n",ab);
	else printf("%lld/%lld\n",ab,aa);
	
	return 0;
}

/*
6 9
1 2 9
1 3 2
2 3 4
2 4 3
2 6 7
3 6 6
3 4 5
4 5 4
4 6 8
1 5
*/
posted @ 2022-07-01 13:35  Feyn618  阅读(24)  评论(0编辑  收藏  举报