1. 程式人生 > >圖論-生成樹-北極通訊網路(二分答案)

圖論-生成樹-北極通訊網路(二分答案)

自己想到的一種解法:二分答案 在實數域上二分d的值,檢驗的辦法就是將距離小於等於的所有點對用並查集合並在一起(也就是在一個聯通塊裡了),最後掃一遍算出一共有多少個聯通塊,如果聯通塊的塊數少於等於k,那麼當前d值合法,否則不合法。 還要注意一個小細節,當最後只有一個聯通塊的時候實際上全圖就已經聯通了不需要衛星裝置,直接返回合法。 此外,當只有一臺衛星裝置的時候和沒有衛星裝置是一樣的。

#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,r,l) for(int i=(r);i>=(l);i--)
#define random(l,r) ((l)+rand()%((r)-(l)+1))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int inf=1e9+10,N=1e4+1000;
const double eps=1e-6;
int n,k,x[N],y[N],fa[N];
double Map[N][N];
int getf(int v){ return fa[v]==v?v:fa[v]=getf(fa[v]);}
void merge(int a,int b){
	fa[getf(b)]=getf(a);
}
bool test(double d){
	rep(i,1,n) fa[i]=i;
	rep(i,2,n) rep(j,1,i-1) if(Map[i][j]<=d) merge(i,j);
	int cnt=0;
	rep(i,1,n) if(fa[i]==i) cnt++;
	if(cnt==1) return true;
	if(cnt<=k) return true;
	return false;
}
int main(){
	cin>>n>>k;
	rep(i,1,n) cin>>x[i]>>y[i],Map[i][i]=0;
	rep(i,2,n) rep(j,1,i-1) Map[i][j]=Map[j][i]=sqrt((x[j]-x[i])*(x[j]-x[i])+(y[j]-y[i])*(y[j]-y[i]));
	double l=0.0f,r=15000.0f;
	while(r-l>eps){
		double mid=(l+r)/2;
		if(test(mid)) r=mid; else l=mid;
	}
	printf("%.2lf",l);
	return 0;
}
//實數域上的二分答案