HDU-1875 畅通工程再续(最小生成树+判断是否存在)

http://acm.hdu.edu.cn/showproblem.php?pid=1875

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 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <string>
  5 #include <math.h>
  6 #include <algorithm>
  7 #include <vector>
  8 #include <stack>
  9 #include <queue>
 10 #include <set>
 11 #include <map>
 12 #include <sstream>
 13 const int INF=0x3f3f3f3f;
 14 typedef long long LL;
 15 const int mod=1e9+7;
 16 //const double PI=acos(-1);
 17 #define Bug cout<<"---------------------"<<endl
 18 const int maxn=1e5+10;
 19 using namespace std;
 20 
 21 struct edge_node
 22 {
 23     int to;
 24     double val;
 25     int next;
 26 }Edge[maxn];
 27 int Head[110];
 28 int tot;
 29 double MST;//存放最小生成树权值和 
 30 
 31 struct node
 32 {
 33     int x;
 34     int y;
 35 }PT[110];//点信息 
 36  
 37 void Add_Edge(int u,int v,double w)
 38 {
 39     Edge[tot].to=v;
 40     Edge[tot].val=w;
 41     Edge[tot].next=Head[u];
 42     Head[u]=tot++;
 43 }
 44 
 45 double lowval[110];
 46 int pre[110];//记录每个点的双亲是谁
 47 
 48 double Prim(int n,int st)//n为顶点的个数,st为最小生成树的开始顶点
 49 {
 50     double sum=0;
 51     fill(lowval,lowval+n,INF);//根据编号从0或是1开始,改+1 
 52     memset(pre,-1,sizeof(pre));
 53     lowval[st]=-1;
 54     pre[st]=-1;
 55     int num=0;//num是目前可以添加到最小生成树中的点的数量 
 56     for(int i=Head[st];i!=-1;i=Edge[i].next)
 57     {
 58         int v=Edge[i].to;
 59         double w=Edge[i].val;
 60         lowval[v]=min(lowval[v],w);
 61         pre[v]=st;
 62         num++;
 63     }
 64     while(num)
 65     {
 66         double MIN=INF;
 67         int k;
 68         for(int i=0;i<n;i++)//根据编号从0或是1开始,改i从0--n-1和1--n
 69         {
 70             if(lowval[i]!=-1&&lowval[i]<MIN)
 71             {
 72                 MIN=lowval[i];
 73                 k=i;
 74             }
 75         }
 76         sum+=MIN;
 77         lowval[k]=-1;
 78         num--;
 79         for(int j=Head[k];j!=-1;j=Edge[j].next)
 80         {
 81             int v=Edge[j].to;
 82             double w=Edge[j].val;
 83             if(w<lowval[v])
 84             {
 85                 if(lowval[v]==INF)
 86                     num++;
 87                 lowval[v]=w;
 88                 pre[v]=k;
 89             }
 90         }
 91     }
 92     for(int i=0;i<n;i++)//判断每个点的pre,看是否有双亲 
 93     {
 94         if(i!=st&&pre[i]==-1)
 95             return INF;
 96     }
 97     return sum;
 98 }
 99 
100 int main()
101 {
102     int T;
103     scanf("%d",&T);
104     while(T--)
105     {
106         int n;
107         scanf("%d",&n);
108         memset(Head,-1,sizeof(Head));
109         tot=0;
110         for(int i=0;i<n;i++)
111             scanf("%d %d",&PT[i].x,&PT[i].y);
112         for(int i=0;i<n;i++)
113         {
114             for(int j=i+1;j<n;j++)
115             {
116                 int x=PT[i].x-PT[j].x;
117                 int y=PT[i].y-PT[j].y;
118                 double val=sqrt(x*x+y*y);
119                 if(val>=10&&val<=1000)
120                 {
121                     Add_Edge(i,j,val);
122                     Add_Edge(j,i,val);
123                 }
124             }
125         }
126         MST=Prim(n,0);
127         if(MST==INF)
128             printf("oh!\n");
129         else
130             printf("%.1f\n",MST*100);
131     }
132     return 0;
133 }

猜你喜欢

转载自www.cnblogs.com/jiamian/p/11737473.html