[校内NOIP2018模拟20181024] 密谋

题目描述

丁国建造了 n 座激光塔。

“ 当若干座激光塔相连并形成环形线路,你就能获得上神的力量。”这是丁国国王从大魔王那得
知的消息。

第二天,丁国国王便下令修建 \(m\) 条连接激光塔的线路。

你作为甲国派来的间谍,无意间听到了这个消息,当即决定破坏这场密谋。每座激光塔的坐标为\((x_i,y_i)\),正在修建的线路\((u_i,v_i)\)表示连接编号为 \(u_i\)\(v_i\) 的激光塔,破坏该条线路的代价为两座激光塔的直线距离。求破坏这场密谋的最小代价。

输入格式

第一行两个整数 \(n, m\)

接下来 \(n\) 行, 每行两个整数 \(x_i\), \(y_i\), 代表点 \(i\) 的坐标

接下来 \(m\) 行, 每行两个整数 \(u_i\), \(v_i\), 代表一条边 \((u_i, v_i)\)

输出格式

输出一个实数代表答案, 当答案与标准答案之差的绝对值不超过 \(10^{-4}\) 时视为正确。

样例数据

input1

3 3
0 0
0 1
1 0
1 2
2 3
1 3

output1

1.000000000

input2

8 8
0 0
3 0
3 3
0 3
1 1
1 2
2 2
2 1
1 2
2 3
3 4
4 1
5 6
6 7
7 8
8 5

output2

4.000000000

数据规模与约定

对于前 \(20\%\)的数据:\(n,m \leq 20\)

对于前 \(50\%\)的数据:\(n,m \leq 1 000\)

对于 \(100\%\) 的数据:\(1 \leq n \leq 10000\) , \(1 \leq m \leq 50000\) , \(|x_i|,|y_i| \leq 10000\) , \(u_i ! = v_i\),不存在两点重合的情况.

时间限制:1s

空间限制:512MB

Solution

没什么话说,想要让无向图没有环,那么只能是一棵树。又要最小代价,那就是最大生成树。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define lowbit(x) ((x)&(-(x)))
using namespace std;
#define REP(i,a,n) for(register int i=(a);i<=(n);++i)
#define PER(i,a,n) for(register int i=(a);i>=(n);--i)
#define FEC(i,x) for(register int i=head[x];i;i=g[i].ne)
template<typename A>inline void read(A&a){a=0;char c=0;int f=1;while(c<'0'||c>'9')(c=getchar())=='-'?f=-1:0;while(c>='0'&&c<='9')a=(a<<3)+(a<<1)+c-'0',c=getchar();f==-1?a=-a:0;}
char buf[30];template<typename A>inline void write(A a){if(a<0)putchar('-'),a=-a;int top=0;if(!a)buf[top=1]='0';while(a)buf[++top]=a%10+'0',a/=10;while(top)putchar(buf[top--]);}
typedef long long ll;typedef unsigned long long ull;
template<typename A,typename B>inline bool SMAX(A&x,const B&y){return y>x?x=y,1:0;}
template<typename A,typename B>inline bool SMIN(A&x,const B&y){return y<x?x=y,1:0;}

const int N=10000+7,M=50000+7;
int n,m;long double ans=0.0;
struct Point{int x,y;}a[N];
struct Graph{int x,y,z;inline bool operator<(const Graph&a)const{return z>a.z;}}G[M];
inline int Dist(int x1,int y1,int x2,int y2){return (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);}

int fa[N];
inline int Find(int x){return x==fa[x]?x:fa[x]=Find(fa[x]);}
inline void Union(int x,int y){x=Find(x),y=Find(y);fa[y]=x;}
inline void Kruskal(){
    for(register int i=1;i<=n;++i)fa[i]=i;
    sort(G+1,G+m+1);
    for(register int i=1;i<=m;++i){
        int x=Find(G[i].x),y=Find(G[i].y),z=G[i].z;if(x==y)continue;
        ans-=sqrt(z);Union(x,y);
    }
}

int main(){
    read(n),read(m);
    for(register int i=1;i<=n;++i)read(a[i].x),read(a[i].y);
    for(register int i=1;i<=m;++i){
        read(G[i].x),read(G[i].y);
        G[i].z=Dist(a[G[i].x].x,a[G[i].x].y,a[G[i].y].x,a[G[i].y].y);ans+=sqrt(G[i].z);
    }
    Kruskal();printf("%.9Lf\n",ans);
}

猜你喜欢

转载自www.cnblogs.com/hankeke/p/20181024-plan.html