I - Swordfish(最小生成树)

题意:给定个点的坐标,求最小生成树。

思路:因为最大只有100,用或者都可以。

这里重新温习一下两个算法:

对所有边排序,每次取最小边,取条边,同时用并查集维护当前图点的集合,如果不在集合里则加入该边。

时间复杂度:为边数。

用一个数组维护当前子图与所有结点的最短距离。任取一结点开始,每次取与其相连的最短边的结点并加入,然后用该结点进行松弛当前子图到所有结点的最短距离.每次找到一条边,一共需要次。

朴素复杂度:

类似用优先队列实现的时间复杂度:

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=100+5;
#define mst(a) memset(a,0,sizeof a)
struct p{
    double x,y;
}a[N];
int s[N];
struct edge{
    int u, v;
    double w;
    bool operator<(const edge& a)const{
        return w<a.w;
    }
}e[N*N];
int find(int x){
    if(s[x]!=x) s[x]=find(s[x]);
    return s[x];
}
int main(){
    int n,k=0;
    while(~scanf("%d",&n)&&n){
        if(k) puts("");
        int id=0;
        double ans=0;
         for(int i=1;i<=n;i++){
             scanf("%lf%lf",&a[i].x,&a[i].y);
             s[i]=i;
             for(int j=1;j<i;j++){
                  double dis=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);
                  dis=sqrt(dis);
                  e[++id]={i,j,dis};
             }
        }
         sort(e+1,e+id+1);
         int cnt=0;
         for(int i=1;i<=id;i++){
              int fa=find(e[i].u),fb=find(e[i].v);
              if(fa==fb) continue;
              cnt++;
              s[fb]=fa;
              ans+=e[i].w;
              if(cnt==n-1) break;
         }
         printf("Case #%d:\n",++k);
         printf("The minimal distance is: %.2lf\n",ans);
    }
    return 0;
} 

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e2+5;
const double inf=1e15;
#define mst(a) memset(a,0,sizeof a)
double a[N][N];
struct p{
    double x,y;
}b[N];
int n,k;
double prim(){
    double d[N]={},ans=0;
    int vis[N]={};
    for(int i=1;i<=n;i++) d[i]=a[1][i];
    vis[1]=1;
    for(int i=2;i<=n;i++){
         double mn=inf;
         int p=0;
         for(int j=1;j<=n;j++)
             if(!vis[j]&&mn>d[j]) mn=d[j],p=j;
         if(mn==inf) break;
         ans+=mn,vis[p]=1;
         for(int j=1;j<=n;j++)    
             if(!vis[j]&&a[p][j]<d[j]) d[j]=a[p][j];
    }
    return ans;
}
int main(){
    while(~scanf("%d",&n)&&n){
        if(k) puts("");
        for(int i=1;i<=n;i++){
            scanf("%lf%lf",&b[i].x,&b[i].y);
            for(int j=1;j<i;j++)
               a[j][i]=a[i][j]=hypot(b[i].x-b[j].x,b[i].y-b[j].y);
        }
        printf("Case #%d:\n",++k);
        printf("The minimal distance is: %.2lf\n",prim());
     }
    return 0;
}