1. 程式人生 > >最小生成樹 kuangbin專題最後一個題

最小生成樹 kuangbin專題最後一個題

題目連結:https://cn.vjudge.net/contest/66965#problem/N

註釋:這道題需要用krustra,用prim的話可能會超時。並且在計算距離的時候要儘量減少步驟,具體注意事項在程式碼中說吧。

AC程式碼:

#include<iostream>
#include<string>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
# define inf 0x3f3f3f3f
# define maxn 5000
int father[maxn];
struct Point
{
    int x,y;
} q[maxn];
struct Edge
{
    int fr;
    int to;
    double cost;
} edge[maxn];
double cal(int t1,int t2)
{
    double s1=(q[t1].x-q[t2].x);
    double s2=(q[t1].y-q[t2].y);
    return (s1*s1+s2*s2);//不要直接計算sqrt,在累積和的時候計算
}
bool cmp(Edge t1,Edge t2)
{
    return t1.cost<t2.cost;
}
int Find(int t)
{
    return t==father[t]? t:father[t]=Find(father[t]);
}
int main()
{
    int T;
   scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d",&q[i].x,&q[i].y);
            father[i]=i;
        }
        int num=0;
        for(int i=1; i<=n; i++)
        {
            for(int j=i+1; j<=n; j++)
            {
                double temp=cal(i,j);
                if(temp<100.0||temp>1000000.0)continue;
                    edge[++num].fr=i;
                    edge[num].to=j;
                    edge[num].cost=temp;
            }
        }
       // cout<<num<<endl;
        sort(edge+1,edge+num+1,cmp);
        double sum=0;
        int ans=0;
        for(int i=1; i<=num; i++)
        {
            int t1=Find(edge[i].fr);
            int t2=Find(edge[i].to);
            if(t1!=t2)
            {
                father[t1]=t2;
                sum+=sqrt(edge[i].cost);
                ans++;
            }
            if(ans==n-1)break;
        }
        if(ans<n-1)printf("oh!\n");
        else printf("%.1lf\n",sum*100.0);
    }
    return 0;
}