bzoj1050【HAOI2006】旅行comf

1050: [HAOI2006]旅行comf

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 2205   Solved: 1174
[ Submit][ Status][ 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

Sample Output

【样例输出1】
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);
	}
}


你可能感兴趣的:(最小生成树,并查集,bzoj)