題解 LuoguP2872【[USACO07DEC]道路建設Building Roads】
阿新 • • 發佈:2019-04-07
... tar using nio ans star void har ==
最小生成樹裸題。
這裏講一下兩點之間的直線距離怎麽算:
\[\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}\]
然後只要將每兩個點之間的距離算出來,已有的邊距離為\(0\),跑一遍最小生成樹就\(OK\)了。
\(Code:\)
#pragma GCC diagnostic error "-std=c++11" #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; template<class T>void r(T &a) { T s=0,w=1;a=0;char ch=getc(stdin); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getc(stdin);} while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getc(stdin);} a=w*s; } template<class T,class... Y>void r(T& t,Y&... a){r(t);r(a...);} int n,m; struct edge { int u,v; double w; }e[1000010]; struct bcj { int father[1010]; void start(int n) {for(int i=0;i<=n;i++)father[i]=i;} int find(int x) {if(father[x]!=x)father[x]=find(father[x]);return father[x];} void unionn(int x,int y) {x=find(x);y=find(y);if(x!=y)father[y]=x;} bool judge(int x,int y) {if(find(x)==find(y))return true;return false;} }; bool cmp(edge a,edge b) { return a.w<b.w; } void kruskal() { bcj uf; int cnt=0; double ans=0.0; sort(e+1,e+1+m,cmp); uf.start(n); for(int i=1;i<=m;i++) { if(!uf.judge(e[i].u,e[i].v)) { cnt++; ans+=e[i].w; uf.unionn(e[i].u,e[i].v); } if(cnt==n-1)break; } printf("%0.2lf",ans); } int x[1010],y[1010]; double jl(int i,int j) { return (double)sqrt((double)(x[i]-x[j])*(double)(x[i]-x[j])+(double)(y[i]-y[j])*(double)(y[i]-y[j])); //這裏必須強制賦值為double,不然會有4個點WA } int main() { int q; r(n,q); for(int i=1;i<=n;i++) r(x[i],y[i]); for(int i=1;i<=q;i++) { m++; r(e[m].u,e[m].v); e[m].w=0.0; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j) { m++; e[m]=(edge){i,j,jl(i,j)}; } kruskal(); return 0; }
題解 LuoguP2872【[USACO07DEC]道路建設Building Roads】