题解:
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步继续执行
#include <iostream>
#include <algorithm>
using namespace std;
struct data{
int u,v,w;
}e[5001];
int father[501];
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int find(int x)
{
if(x!=father[x]) father[x]=find(father[x]);
return father[x];
}
bool cmp(const data &a,const data &b)
{
return a.w<b.w;
}
int main()
{
int i,x,u,v,mx,mn,r,start=0;
int n,m,s,t,ansmx=1,ansmn=0;
cin>>n>>m;
for(int i=0;i<m;i++)
cin>>e[i].u>>e[i].v>>e[i].w;
sort(e,e+m,cmp);
cin>>s>>t;
while(start<m)
{
mn=mx=-1;
for(i=1;i<=n;i++)
father[i]=i;
for(x=start;x<m;x++)
{
u=find(e[x].u);v=find(e[x].v);father[u]=v;
if(find(s)==find(t))
{
mx=e[x].w;break;
}
}
if(mx==-1)
{
if(!ansmn){
cout<<"IMPOSSIBLE";return 0;
}
else break;
}
for(i=1;i<=n;i++)
father[i]=i;
for(;x>=0;x--)
{
u=find(e[x].u);v=find(e[x].v);father[u]=v;
if(find(s)==find(t))
{
mn=e[x].w;break;
}
}
start=x+1;
if(mn==-1)
{
if(!ansmn){
cout<<"IMPOSSIBLE";return 0;
}
else break;
}
int r=gcd(mx,mn);mx/=r;mn/=r;
if(ansmx*mn>ansmn*mx)
{
ansmn=mn;ansmx=mx;
}
}
if(ansmn==1) cout<<ansmx;
else cout<<ansmx<<"/"<<ansmn<<endl;
return 0;
}