1050: [HAOI2006]旅行comf
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2205 Solved: 1174
[Submit][][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不可能同样。
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
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
IMPOSSIBLE
【例子输出2】
5/4
【例子输出3】
2
HINT
【数据范围】
1< N < = 500
1 < = x, y < = N,0 < v < 30000,x ≠ y
0 < M < =5000
Source
思路非常像最小生成树。
先将边依照权值从小到大排序。
枚举最小边,将其它边按顺序依次加进去,直到s和t属于一个集合,用并查集维护。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 505
#define maxm 5005
using namespace std;
struct data{int x,y,z;}a[maxm];
int n,m,s,t,mn,mx,p[maxn];
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline bool cmp(data a1,data a2)
{
return a1.z<a2.z;
}
inline int find(int x)
{
return p[x]==x?x:p[x]=find(p[x]);
}
inline void merge(int x,int y)
{
int fx=find(x),fy=find(y);
if (fx!=fy) p[fx]=fy;
}
inline int gcd(int x,int y)
{
return y? gcd(y,x%y):x;
}
int main()
{
n=read();m=read();
F(i,1,m){a[i].x=read();a[i].y=read();a[i].z=read();}
sort(a+1,a+m+1,cmp);
s=read();t=read();
F(i,1,m)
{
F(j,1,n) p[j]=j;
merge(a[i].x,a[i].y);
int tmp=i;
while (tmp<m&&find(s)!=find(t))
{
tmp++;
merge(a[tmp].x,a[tmp].y);
}
if (find(s)!=find(t)) continue;
if (tmp>m) tmp=i;
if (!mx||(a[tmp].z*1.0/a[i].z<mx*1.0/mn))
{
mx=a[tmp].z;
mn=a[i].z;
}
}
if (!mx) printf("IMPOSSIBLE\n");
else if (mx%mn==0) printf("%d\n",mx/mn);
else
{
int tmp=gcd(mx,mn);
printf("%d/%d\n",mx/tmp,mn/tmp);
}
}