求删点后最小的生成树,n<50.。。。数据好弱,直接暴力枚举就行。。。删点的时候直接g[i][j]=INF就行了。
#include<iostream>
#include<algorithm>
#include<fstream>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<map>
#include<set>
#define FF(i, a, b) for(i=a; i<b; i++)
#define FD(i, a, b) for(i=a; i>b; i--)
#define CLR(a, b) memset(a, b, sizeof(a))
#define LL long long
#define CPY(a, b) memcpy(a, b, sizeof(b))
using namespace std;
ofstream fout ("output.txt");
ifstream fin ("input.txt"); const int maxn = 100;
const double INF = 222222;
int T, n;
double g[maxn][maxn], low[maxn], x[maxn], y[maxn], tmp[maxn][maxn];
bool vis[maxn]; double prim(int start)
{
double min, res=0;
int i, j, pos;
CLR(vis, 0);
vis[start] = 1; pos = start;
FF(i, 1, n+1) if(i!=pos) low[i] = g[pos][i];
FF(i, 1, n)
{
min = INF;
FF(j, 1, n+1)
if(vis[j] == 0 && min > low[j])
min = low[j], pos = j;
res += min;
vis[pos] = 1;
FF(j, 1, n+1)
if(vis[j] == 0 && low[j] > g[pos][j])
low[j] = g[pos][j];
}
return res;
} int main()
{
scanf("%d", &T);
while(T--)
{
int i, j;
scanf("%d", &n);
FF(i, 1, n+1) scanf("%lf%lf", &x[i], &y[i]);
FF(i, 1, n+1)
FF(j, 1, n+1)
g[i][j] = sqrt((x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]));
double ans = INF*INF;
FF(i, 1, n+1)
{
CPY(tmp, g);
FF(j, 1, n+1)
{
g[i][j] = g[j][i] = INF;
}
ans = min(ans, prim(1));
CPY(g, tmp);
}
printf("%.2lf\n", n < 3 ? 0 : ans-INF);
}
return 0;
}