标签:logs scanf pac == log while printf double for
题目:洛谷P2872、POJ3625。
题目大意:给你n个点的坐标,有些点已经有边连通,现在要你连上剩下的所有点,求这些边的最小长度是多少(不包括原来的边)。
解题思路:最小生成树,把所有边处理出来,跑Kruskal即可。注意原来有的边优先级最高且长度不加进答案。由于边的总数是$n^2$级别的,所以时间复杂度$O(n^2\log n^2)$。
C++ Code:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int n,m,fa[1005],cnt; int b[1005][1005]; struct zb{ int x,y; }a[1005]; struct edge{ int u,v; double l; int b; bool operator <(const edge& rhs)const{ if(b!=rhs.b)return b>rhs.b; return l<rhs.l; } }e[1000005]; int dad(int x){return(fa[x]==x)?(x):(fa[x]=dad(fa[x]));} int main(){ memset(b,0,sizeof b); scanf("%d%d",&n,&m); for(int i=1;i<=n;++i)fa[i]=i,scanf("%d%d",&a[i].x,&a[i].y); while(m--){ int x,y; scanf("%d%d",&x,&y); b[x][y]=b[y][x]=1; } cnt=0; for(int i=1;i<n;++i) for(int j=i+1;j<=n;++j){ e[++cnt]=(edge){i,j,sqrt((double)(a[i].x-a[j].x)*(a[i].x-a[j].x)+(double)(a[i].y-a[j].y)*(a[i].y-a[j].y)),b[i][j]}; } sort(e+1,e+cnt+1); double ans=0; for(int i=1,k=0;i<=cnt&&k!=n-1;++i){ int x=dad(e[i].u),y=dad(e[i].v); if(x!=y){ fa[y]=x; if(!e[i].b)ans+=e[i].l; ++k; } } printf("%.2f\n",ans); return 0; }
[USACO07DEC]道路建设Building Roads
标签:logs scanf pac == log while printf double for
原文地址:http://www.cnblogs.com/Mrsrz/p/7416414.html