【最短路问题】 hdu 1875 畅通工程再续


畅通工程再续

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 30847    Accepted Submission(s): 10079


Problem Description
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组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!

 代码1(Kruskal):

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 99999999;
using namespace std;
int pre[10001];
struct dao{
   int x,y;
   double z;
}a[100001];
void init(){
   for(int j=0;j<=3000;j++)
      pre[j]=j;
}

int find1(int x){          //找父亲
    int r=x;
    while(pre[r]!=r)
        r=pre[r];
    int i=x,j;
    while(pre[i]!=r){
        j=pre[i];
        pre[i]=r;
        i=j;
    }

    return r;
}
int mix(int x,int y){    //如否成环
   int x1=find1(x);
   int y1=find1(y);
   if(x1!=y1){
      pre[y1]=x1;
      return 1;
   }
   return 0;
}

bool cmp(struct dao q,struct dao w){  //排序
    return q.z<w.z;
}
int main(){
   int t;
     cin>>t;
   while(t--){
      init();
      int n,j,k,i,x[10001],y[10001];
         cin>>n;
      double l;
      i=1;
      for(j=1;j<=n;j++){
         cin>>x[j]>>y[j];
         for(k=1;k<j;k++){       //路径长度 和方向
            l=sqrt((double)(x[j]-x[k])*(double)(x[j]-x[k])+(double)(y[j]-y[k])*(double)(y[j]-y[k]));
            a[i].x=k;
            a[i].y=j;
            a[i].z=l;//cout<<a[i].z<<endl;
            i++;

         }
      }//cout<<"1"<<endl;

      double s=0;
      int cut=0;
      sort(a+1,a+i,cmp);
      //for(int m=1;m<=i;m++){
       //  cout<<a[m].z<<endl;
      //}
      for(k=1;k<=i;k++){
        if(a[k].z<10||a[k].z>1000){
            continue;
        }
        else{
            if(mix(a[k].x,a[k].y)){   //是否成环
                cut++;
                s+=a[k].z*100;

            }

        }    //cout<<s<<endl;
        if(cut==n-1) break;
     }

     if(cut<n-1) printf("oh!\n");
     else printf("%.1lf\n",s);
   }

   return 0;
}


prim  总是出错 要炸了!!! md

用的别人的代码  md  好气 

#include <cstdio>  
#include <cstring>  
#include <cstdlib>  
#include <cmath>  
#include <string>  
#include <iostream>  
#include <stack>  
#include <queue>  
#include <vector>  
#include <algorithm>  
#define mem(a,b) memset(a,b,sizeof(a))  
#define N 100+20  
#define M 10000+20  
#define MOD 1000000000+7  
#define inf 0x3f3f3f3f  
using namespace std;  
int n,x[N],y[N];  
bool vis[N];  
double map[N][N],dis[N];  
void Prim()  
{  
    double minn;  
    int k;  
    for(int i=1; i<=n; i++)  
    {  
        dis[i]=map[1][i];  
        vis[i]=0;  
    }  
    vis[1]=1;  
    double sum=0;  
    for(int i=1; i<=n-1; i++)//一共要进行n-1次  
    {  
        minn=inf;  
        for(int j=1; j<=n; j++)  
        {  
            if(!vis[j]&&dis[j]<minn)  
            {  
                minn=dis[j];  
                k=j;  
            }  
        }  
        if(minn==inf)//minn的值没有改变的话,那就是没有符合条件的  
        {  
            printf("oh!\n");  
            return;  
        }  
        vis[k]=1;  
        sum+=dis[k];//把选定的加上  
        for(int j=1; j<=n; j++)  
            if(!vis[j]&&map[k][j]<dis[j])  
                dis[j]=map[k][j];  
    }  
    printf("%.1lf\n",sum*100);  
}  
int main()  
{  
    int t;  
    scanf("%d",&t);  
    while(t--)  
    {  
        scanf("%d",&n);  
        double w;  
        for(int i=1; i<=n; i++)  
            for(int j=1; j<=n; j++)  
                i==j?map[i][j]=0:map[i][j]=inf;  
        for(int i=1; i<=n; i++)  
        {  
            scanf("%d%d",&x[i],&y[i]);  
            for(int j=1; j<i; j++)//计算多组数据的距离  
            {  
                w=sqrt((double)(x[i]-x[j])*(double)(x[i]-x[j])+(double)(y[i]-y[j])*(double)(y[i]-y[j]));  
                if(w>1000||w<10)//不满足条件的直接设为无穷大  
                    map[i][j]=map[j][i]=inf;  
                else  
                    map[i][j]=map[j][i]=w;  
            }  
        }  
        Prim();  
    }  
    return 0;  
}  

   


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值