【ICPC-343】hdu 4463 Outlets

点击打开链接hdu 4463

 

思路:最小生成树+kruskal

 

 

分析:
1 题目要求的找到n个商店组成n-1条边,并且要求耐克和苹果商店肯定要相连,求最短长度
2 很明显的最小生成树的模板题,由于要求耐克和苹果的商店要在一起那么就要把这两个商店编号合并到同一个集合,然后在利用kruskal计算。

 

 

代码:

 


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

#define MAXN 10010
#define N 55

double ans;
int n , P , Q , pos;
int father[MAXN];
int rank[MAXN];
struct Point{
   int x;
   int y;
}p[N];
struct Edge{
   int x;
   int y;
   double value;
}e[MAXN];

bool cmp(Edge e1 , Edge e2){
   return e1.value < e2.value;
}

void init(){
   pos = 0;
   for(int i = 1 ; i <= n ; i++){
      for(int j = i+1 ; j <= n ; j++){
         double tmpx = (p[i].x-p[j].x)*(p[i].x-p[j].x);
         double tmpy = (p[i].y-p[j].y)*(p[i].y-p[j].y);
         double tmp = sqrt(tmpx+tmpy);
         e[pos].x = i , e[pos].y = j;
         e[pos++].value = tmp;
         if(i == P && j == Q)
            ans = tmp;
      }
   }
}

void init_Set(){
   for(int i = 0 ; i <= n ; i++){
      father[i]= i;
      rank[i] = 0;
   }
}

int find_Set(int x){
   if(father[x] != x)
     father[x] = find_Set(father[x]);
   return father[x];
}

void union_Set(int x  , int y){
   if(rank[x] > rank[y])
     father[y] = x;
   else{
     if(rank[x] == rank[y])
       rank[y]++;
     father[x] = y;
   }
}

void kruskal(){

   init();
   init_Set();
   sort(e , e+pos , cmp);
   union_Set(P , Q);

   for(int i = 0 ; i < pos ; i++){
      int root_x = find_Set(e[i].x);
      int root_y = find_Set(e[i].y);
      if(root_x != root_y){
         ans += e[i].value;
         union_Set(root_x , root_y);
      }
   }
}

int main(){
   while(scanf("%d" , &n) && n){
      scanf("%d%d" , &P , &Q);
      if(P > Q)
         swap(P , Q);
      for(int i = 1 ; i <= n ; i++)
         scanf("%d%d" , &p[i].x , &p[i].y);
      kruskal();
      printf("%0.2lf\n" , ans);
   }
   return 0;
}

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值