P2502 [HAOI2006]旅行 并查集

时间:2023-03-09 08:05:32
P2502 [HAOI2006]旅行 并查集

  

题目描述

Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。Z小镇附近共有N个景点(编号为1,2,3,…,N),这些景点被M条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路。也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。速度变化太快使得游客们很不舒服,因此从一个景点前往另一个景点的时候,大家都希望选择行使过程中最大速度和最小速度的比尽可能小的路线,也就是所谓最舒适的路线。

输入输出格式

输入格式:

第一行包含两个正整数,N和M。

接下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路,车辆必须以速度v在该公路上行驶。

最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。

输出格式:

如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。

输入输出样例

输入样例#1: 复制
4 2
1 2 1
3 4 2
1 4
输出样例#1: 复制
IMPOSSIBLE
输入样例#2: 复制
3 3
1 2 10
1 2 5
2 3 8
1 3
输出样例#2: 复制
5/4
输入样例#3: 复制
3 2
1 2 2
2 3 4
1 3
输出样例#3: 复制
2

要求所经过的路程的最大权值尽可能小   最小权值尽可能大  使得 最大权值/最小权值  最小        
可以先将所有边从小到大排序好
然后枚举最小权值i 然后j从i开始往m遍历 (当遍历过程中正好联通时立刻退出 (贪心原理) ) 犯了一个巨大错误:如果不是全局变量一定要初始化 我因为没有初始化然后wa的点每次都不一样!!!!!
还有就是注意细节
排序的思想很好
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);i--)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define LL long long
#define pb push_back
#define fi first
#define REP(i,N) for(int i=0;i<(N);i++)
#define CLR(A,v) memset(A,v,sizeof A)
///////////////////////////////////
#define inf 0x3f3f3f3f
#define N 6000+6
int f[N]; int gcd(int x,int y)
{
return y==?x:gcd(y,x%y);
} int find1(int x)
{
return x==f[x]?x:f[x]=find1(f[x]);
}
void union1(int a,int b)
{
int x=find1(a);
int y=find1(b);
if(x!=y)
f[x]=y;
} struct node
{
int s,e,len; }edge[N]; bool cmp(node a,node b)
{
return a.len<b.len;
} int main()
{
int n,m;
RII(n,m); rep(i,,m)
RIII(edge[i].s,edge[i].e,edge[i].len);
int s,e;
RII(s,e); int ans1=,ans2=;
sort(edge+,edge++m,cmp);
rep(i,,m)
{
rep(j,,n)
f[j]=j;
int j;
for(j=i;j<=m;j++)
{
if(find1(edge[j].s)==find1(edge[j].e))continue;
union1(edge[j].s,edge[j].e);
if(find1(s)==find1(e))break;
}
if(i==&&(find1(s)!=find1(e)) )
{
printf("IMPOSSIBLE");
return ;
}
if(find1(s)!=find1(e))break;
if(ans1*edge[i].len>=ans2*edge[j].len)
ans1=edge[j].len,ans2=edge[i].len;
}
int x=gcd(ans1,ans2);
if (x==ans2) printf("%d\n",ans1/ans2); else printf("%d/%d\n",ans1/x,ans2/x);
}