nyoj 711 枚举+并查集

并查集与路径查找
本文介绍了一种使用并查集解决从起点s到终点t的路径查找问题的方法,并通过枚举边的方式寻找最小和最大边值之间的最优比值。
 #include<stdio.h>//从大到小不断枚举边直到找到s-t的路径,判断从s可以到t可以用并查集来判断
#include<stdlib.h>//枚举最大的一条边肯定要找和他的值最接近的边,所以要排序
#define N 5100
#define  inf  0x3fffffff
struct node {
int u,v,speed;
}map[N];
int gcd(int a,int b) {
if(b==0)
    return a;
return gcd(b,a%b);
}
int cmp(const void *a,const void *b) {
return  (*(struct node *)b).speed-(*(struct node *)a).speed;
}
int pre[510];
int find(int x) {
  if(x!=pre[x])
    pre[x]=find(pre[x]);
  return pre[x];
}
int main(){
     int min,max,mi,ma,i,j,k,tt,t,n,m,s,a,b;
     scanf("%d",&tt);
     while(tt--) {
            scanf("%d%d",&n,&m);
     for(i=0;i<m;i++)//
        scanf("%d%d%d",&map[i].u,&map[i].v,&map[i].speed);
        scanf("%d%d",&s,&t);
        max=inf;min=1;//初始化比值为最大
     qsort(map,m,sizeof(map[0]),cmp);//排序从大到小
     for(i=0;i<m;i++) {
        for(j=1;j<=n;j++)
        pre[j]=j;
        mi=inf;ma=-1;
        for(j=i;j<m;j++) {
            a=find(map[j].u);
            b=find(map[j].v);
            if(a!=b) {//如果两个点之间的路径没有加过
                pre[b]=a;
                if(mi>map[j].speed)//当前路中的最小值
                    mi=map[j].speed;
                if(ma<map[j].speed)//当前路中的最大值
                    ma=map[j].speed;
            }
            if(find(s)==find(t))//当前边加入后是否可以联通s-t
                break;
        }
        if(j==m)//如果找不到直接退出
            break;
        if(max*mi>min*ma) {//更新最小比值
            max=ma;
            min=mi;
        }
     }
     if(max%min==inf) {//如果没有s-t的路径输出
        printf("IMPOSSIBLE\n");
        continue;
     }
     if(max%min==0)
        printf("%d\n",max/min);
     else {//如果不能整除
            k=gcd(max,min);
     printf("%d/%d\n",max/k,min/k);
     }
     }
return 0;

转载于:https://www.cnblogs.com/thefirstfeeling/p/4410804.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值