题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1875
题意:中文题0.0
思路:先连接每条边,再kruskal一下,如果加入边的权值<10或>1000,就不连接,否则就连接并计数t。如果t==n-1,即等于需要连接的边数,那么就代表可以连接,否则不行
代码:
#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <numeric>
#include <set>
#include <string>
#include <cctype>
#include <sstream>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 5e5 + 5;
int n,p[105],cnt,t;
struct point{
int x,y;
}po[maxn];
struct edge{
int u,v;
double cost;
}e[maxn];
bool cmp(edge a,edge b){
return a.cost<b.cost;
}
void init (int n) {for (int i=0;i<=n;i++) p[i]=i;}
int Find(int x) {return p[x]==x?x: ( p[x]=Find ( p[x] ) );}
bool same(int a,int b) {return Find(a)==Find(b);}
void unite (int x,int y)
{
x=Find(x);
y=Find(y);
if (x!=y) p[x]=y;
}
double dis(point a,point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double kruskal(){
sort(e,e+cnt,cmp);
double ans=0;
int t=0;
for (int i=0;i<cnt;i++){
edge ee=e[i];
if (!same(ee.u,ee.v)){
if (ee.cost<10||ee.cost>1000) continue;
unite(ee.u,ee.v);
ans+=ee.cost*100;
t++;
}
}
if (t==n-1) return ans;
else return -1;
}
int main () {
//freopen ("in.txt", "r", stdin);
scanf ("%d",&t);
while (t--){
scanf ("%d",&n);
init(n);
for (int i=1;i<=n;i++){
scanf ("%d%d",&po[i].x,&po[i].y);
}
cnt=0;
for (int i=1;i<=n;i++){
for (int j=i+1;j<=n;j++){
e[cnt].u=i;
e[cnt].v=j;
e[cnt++].cost=dis(po[i],po[j]);
}
}
double ans=kruskal();
if (ans!=-1) printf ("%.1f\n",ans);
else printf ("oh!\n");
}
return 0;
}