畅通工程再续 【kruskal】 【 prime】

相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。
Input
输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。
每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。
Output
每组输入数据输出一行,代表建桥的最小花费,结果保留一位小数。如果无法实现工程以达到全部畅通,输出”oh!”.
Sample Input
2
2
10 10
20 20
3
1 1
2 2
1000 1000
Sample Output
1414.2
oh!

一 kruskal 代码 78ms

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#define CLR(a,b) memset((a),(b),sizeof(a))
#define inf 0x3f3f3f3f
#define mod 100009
#define LL long long
#define M  10000+10
#define ll o<<1
#define rr o<<1|1
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
using namespace std;
int c;
int pre[M];
struct Dot{int x,y;} dot[M];
struct edge {int  from,to; double cost;}G[M];
double dis(Dot a,Dot b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
int find(int x){ return x==pre[x] ? x:pre[x]=find(pre[x]);}
void join(int x,int y){pre[find(x)]=find(y);}
int same(int x,int y){ return find(x)==find(y);}
int cmp(edge a,edge b){ return a.cost<b.cost;}
int k;
void init(){ for(int i=0;i<c;i++) pre[i]=i;}
void getmap()
{   
        k=0;
        for(int i=0;i<c;i++)
        scanf("%d%d",&dot[i].x,&dot[i].y);

        for(int i=0;i<c;i++)
        {
            for(int j=i+1;j<c;j++)
             {
                double d=dis(dot[i],dot[j]);
                if((fabs(d-10.0)<1e-8||d>10.0)&&(fabs(d-1000.0)<1e-8||d<1000.00))
                {
                    G[k].from=i;
                    G[k].to=j;
                    G[k++].cost=d;
                 }
              } 
         }
         sort(G,G+k,cmp);
}
int check()  //  判定连通的 
{
    int i,j;
    int num=0;
    for(i=0;i<c;i++)
    {
        if(i==pre[i]) {
            num++;
            if(num>1) return 0;
        }
     } 
    return 1;
}
void krus()
{
    int i,j;
    double sum=0;
    for(i=0;i<k;i++)
    {
        if(!same(G[i].from,G[i].to))
        {
            sum+=G[i].cost;
            join(G[i].from,G[i].to);
        }
    }
    if(check()) printf("%.1lf\n",sum*100);
    else puts("oh!"); 
}
int main()
{
    int  t;
    scanf("%d",&t);while(t--)
    {
        scanf("%d",&c);
        init();
        getmap();
        krus();
    }
    return 0;
}

二 prime 46ms

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#define CLR(a,b) memset((a),(b),sizeof(a))
#define inf 0x3f3f3f3f
#define mod 100009
#define LL long long
#define M  200
#define ll o<<1
#define rr o<<1|1
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
using namespace std;
int vis[M];
double mp[M][M];
double dis[M];
int n;
struct Dot { int x,y;} dot[M];
double diss(Dot a,Dot b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
void init()
{
    int i,j;
     for(i=0;i<n;i++)   //  这个初始化   
  {
    vis[i]=0;
    for(j=0;j<n;j++)
    {
        if(i==j) mp[i][j]=0 ;
        else mp[i][j]=mp[j][i]=inf;
     }
    }
 }
void getmap()
{
    int i,j;
    for(i=0;i<n;i++)
    scanf("%d%d",&dot[i].x,&dot[i].y);

    for(i=0;i<n;i++)  //  这里的建图 不和 kruskas 算法一样,手残 ,WA了好几次这里 
    {
        for(j=0;j<n;j++)
        {
            if(i==j) continue;
            double d=diss(dot[i],dot[j]);
            if((fabs(d-10.0)<1e-8||d>10.0)&&(fabs(d-1000.0)<1e-8||d<1000.00))
            {
                mp[i][j]=mp[j][i]=d;
            }
        }
    }
}

void prime()
{
    int i,j;
    double sum=0; 
    int now,next;
    for(i=0;i<n;i++)
    dis[i]=mp[0][i];
    vis[0]=1; dis[0]=0;
    for(j=1;j<n;j++)
    {
        double min=inf;
        next=-1;
        for(i=0;i<n;i++)
        {
            if(!vis[i]&&dis[i]<min) 
            {
                min=dis[i];
                next=i;
             }
         }
         if(next==-1) 
         {
            puts("oh!");
            return ;
         }
         vis[next]=1; sum+=dis[next];
         for(i=0;i<n;i++)
         {
            if(!vis[i]&&dis[i]>mp[next][i])
            {
                dis[i]=mp[next][i];
             }
         }
     }
      printf("%.1f\n",sum*100);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        init();
        getmap();
        prime();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值