题目链接:HDU 1875 畅通工程再续
Kruskal + 并查集。
跟上道题类似,转化一下就好了。
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <cmath>
using namespace std;
const int MAX_M = 100 + 10;
const int MAX_N = (MAX_M * (MAX_M - 1)) >> 1;
double w[MAX_N];
int u[MAX_N],v[MAX_N],p[MAX_M],r[MAX_N];
struct Point
{
int x,y;
};
Point point[MAX_M];
int cmp(int i,int j)
{
return w[i] < w[j];
}
int _find(int x)
{
return x == p[x] ? x : (p[x] = _find(p[x]));
}
double dis(int i,int j)
{
return sqrt((point[i].x - point[j].x) * (point[i].x - point[j].x) + (point[i].y - point[j].y) * (point[i].y - point[j].y));
}
bool ok(int i,int j)
{
double d = dis(i,j);
if(d < 10.0 || d > 1000.0)
return false;
return true;
}
int C,T;
double ans;
int main()
{
cin >> T;
while(T--)
{
ans = 0.0;
cin >> C;
for(int i = 1;i <= C;i++)
{
p[i] = i;
cin >> point[i].x >> point[i].y;
}
int cnt = 1;
for(int i = 1;i <= C;i++)
{
for(int j = i + 1;j <= C;j++)
{
if(!ok(i,j))
continue;
u[cnt] = i;
v[cnt] = j;
w[cnt] = dis(i,j);
r[cnt] = cnt;
cnt++;
}
}
sort(r + 1,r + cnt,cmp);
int a,b;
for(int i = 1;i < cnt;i++)
{
a = _find(u[r[i]]);
b = _find(v[r[i]]);
if(a != b)
{
p[a] = b;
C--;
ans += w[r[i]];
}
}
ans *= 100;
if(C == 1)
cout << fixed << setprecision(1) << ans << endl;
else
cout << "oh!" << endl;
}
return 0;
}