nyoj711
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=711
并查集: 一般用于无向图中。
本题题意: 从s <---- > t 来回游动 , 求这条路上 存在的最大速度 与 最小速度 的比率 最小。
暴力枚举 ,速度从大向小排列 ,从小到大排都可以 ! , 找到一个 合适的比率(在s 到 t 通路的情况下 ) ,(分子上速度越小 ,比率越小, 分母上 速度越大 ,比率越小 ),枚举过程中找到一个折中 ,合适的条件 。并查集在本题中的作用是将能连通的点,划分到一个集合里,用于判断点 到点之间是否连通。
#include<stdio.h>
#include<algorithm>
using namespace std;
#define INF 1<<30
int cou[505];
typedef struct
{
int q,h,v;
}E;
E e[5000];
int cmp( E a , E b)
{
if(a.v > b.v) return 1;
return 0;
}
int find( int v )
{
if( cou[v] == v ) return v;
cou[v] = find(cou[v]);
return cou[v] ;
}
void union_e(int v,int u)
{
int x = find(v);
int y = find(u);
cou[x] = y;
}
int gcd(int m, int n)
{
if(m%n!= 0)
return gcd(n,m%n);
return n;
}
void set(int cot )
{
int i;
for(i = 0;i <= cot ;i++)
cou[i] = i;
}
int main()
{
int n;
scanf("%d",&n);
double rate ;
int maxv = 0,minv= 0,s,t,var,cot,i,j,r;
while(n -- )
{
scanf("%d %d",&cot,&var);
for(i=0;i<var;i++)
{
scanf("%d %d %d",&e[i].q,&e[i].h,&e[i].v);
}
scanf("%d %d",&s,&t);
sort(e,e+var,cmp);
rate = INF;
for(i = 0;i<var;i++)
{
set(cot);
for(j = i;j<var;j++)
{
if( find( e[j].q ) != find(e[j].h) )
{
union_e( e[j].q ,e[j].h );
}
// printf("%d %d\n",i,j);
if(find(s) == find(t))break;
}
if(j == var )continue;
if( e[i].v*1.0 /e[j].v < rate)
{
rate = e[i].v*1.0 /e[j].v ;
maxv = e[i].v;
minv = e[j].v;
}
}
if(rate == INF)printf("IMPOSSIBLE\n");
else if( maxv % minv == 0)
printf("%d\n",maxv/minv);
else
{
r = gcd(maxv,minv);
printf("%d/%d\n",maxv/r,minv/r);
}
}
return 0;
}
有一个比较快的代码 ,减少调用函数次数 ,gcd 优化
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<climits>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<string>
#include<stack>
#include<map>
#define ll long long
#define MAX 5010
#define INF INT_MAX
#define eps 1e-6
#define REP(i,n) for (int i=0; i<(n); i++)
#define FOR(i,s,t) for (int i=(s); i<=(t); i++)
using namespace std;
struct Edge{
int from,to,w;
}p[MAX];
int fa[MAX];
int find(int x){
return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
bool cmp(struct Edge x,struct Edge y){
return x.w > y.w;
}
int gcd(int x,int y){
if (!y) return x;
else return gcd(y,x%y);
}
int main(){
int T,n,m,s,t;
scanf("%d",&T);
while (T--){
scanf("%d%d",&n,&m);
for (int i=0; i<m; i++){
scanf("%d%d%d",&p[i].from,&p[i].to,&p[i].w);
}
scanf("%d%d",&s,&t);
sort(p,p+m,cmp);
// for (int i=0; i<m; i++)
// printf("%d %d %d\n",p[i].from,p[i].to,p[i].w);
double ans = INF*1.0;
int u,v,ok = 0;
for (int i=0; i<m; i++){
for (int j=0; j<=n; j++) fa[j] = j;
int j;
for (j=i; j<m; j++){
int x = find(p[j].from),y = find(p[j].to);
if (x != y){
if (x > y) fa[y] = x;
else fa[x] = y;
}
if (find(s) == find(t)){
ok = 1;
break;
}
}
if (j >= m) break;
if (ans > p[i].w*1.0 / p[j].w){
ans = p[i].w*1.0 / p[j].w;
u = p[i].w;
v = p[j].w;
}
}
if (!ok) printf("IMPOSSIBLE\n");
else if (u % v == 0) printf("%d\n",u/v);
else printf("%d/%d\n",u/gcd(u,v),v/gcd(u,v));
}
return 0;
}