hdu 4463 第37届ACM/ICPC杭州赛区K题 最小生成树
题意:给坐标系上的一些点,其中有两个点已经连了一条边,求最小生成树的值
将已连接的两点权值置为0,这样一定能加入最小生成树里
最后的结果加上这两点的距离即为所求
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3f3f3f; 11 const double eps=1e-5; 12 #define cl(a) memset(a,0,sizeof(a)) 13 #define ts printf("*****\n"); 14 int n,m,tt; 15 const int MAXN=110;//最大点数 16 const int MAXM=10000;//最大边数 17 int F[MAXN];//并查集使用 18 struct Edge 19 { 20 int u,v; 21 double w; 22 }edge[MAXM];//存储边的信息,包括起点/终点/权值 23 int tol;//边数,加边前赋值为0 24 void addedge(int u,int v,double w) 25 { 26 edge[tol].u=u; 27 edge[tol].v=v; 28 edge[tol++].w=w; 29 } 30 bool cmp(Edge a,Edge b) 31 {//排序函数,讲边按照权值从小到大排序 32 return a.w<b.w; 33 } 34 int find(int x) 35 { 36 if(F[x]==-1)return x; 37 else return F[x]=find(F[x]); 38 } 39 double Kruskal(int n)//传入点数,返回最小生成树的权值,如果不连通返回-1 40 { 41 memset(F,-1,sizeof(F)); 42 sort(edge,edge+tol,cmp); 43 int cnt=0;//计算加入的边数 44 double ans=0; 45 for(int i=0;i<tol;i++) 46 { 47 int u=edge[i].u; 48 int v=edge[i].v; 49 double w=edge[i].w; 50 int t1=find(u); 51 int t2=find(v); 52 if(t1!=t2) 53 { 54 ans+=w; 55 F[t1]=t2; 56 cnt++; 57 } 58 if(cnt==n-1)break; 59 } 60 if(cnt<n-1)return -1;//不连通 61 else return ans; 62 } 63 struct node 64 { 65 double x,y; 66 void in() 67 { 68 scanf("%lf%lf",&x,&y); 69 } 70 }nn[MAXN]; 71 double dist(node a,node b) 72 { 73 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 74 } 75 int main() 76 { 77 int i,j,k; 78 #ifndef ONLINE_JUDGE 79 freopen("1.in","r",stdin); 80 #endif 81 while(scanf("%d",&n)!=EOF) 82 { 83 tol=0; 84 if(n==0) break; 85 int q,p; 86 scanf("%d%d",&p,&q); 87 p--,q--; 88 for(i=0;i<n;i++) 89 { 90 nn[i].in(); 91 } 92 for(i=0;i<n;i++) 93 { 94 for(j=i+1;j<n;j++) 95 { 96 addedge(i,j,dist(nn[i],nn[j])); 97 if((i==p&&j==q)||(i==q&&j==p)) 98 { 99 addedge(i,j,0); 100 } 101 } 102 } 103 printf("%.2lf\n",Kruskal(n)+dist(nn[p],nn[q])); 104 } 105 }