nyoj711最舒适的路线 (枚举 + 并查集 )

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sinat_26019265/article/details/51474568


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;
}














                

  

      

展开阅读全文

没有更多推荐了,返回首页