poj1751最小生成树

题目:http://poj.org/problem?id=1751
两种算法思路:https://www.cnblogs.com/PJQOOO/p/3855017.html
方法:
1.普利姆算法(数组大小开小了导致一直wa)

#include<cstdio>
#include<cmath>
#define len 760
#define inf 10000000
using namespace std;
int vis[len],t[len][2],pre[len],n,m,map[len][len],d[len];
int dkr(int x1,int y1,int x2,int y2)
{
    return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
void prim()
{
     for(int i=1;i<=n;i++)
    {
        vis[i]=0;
        d[i]=map[i][1];
        pre[i]=1;
    }
    d[1]=1;
    vis[1]=1;
    for(int i=1;i<n;i++)
    {
        int k,t1=inf;
        for(int j=1;j<=n;j++) if(vis[j]==0&&d[j]<t1) k=j,t1=d[j];
        vis[k]=1;
        if(map[pre[k]][k]) printf("%d %d\n",pre[k],k);
        for(int j=1;j<=n;j++) if(vis[j]==0&&d[j]>map[k][j]) d[j]=map[k][j],pre[j]=k;
    }
}
int main()
{
        int a,b;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d%d",&t[i][0],&t[i][1]);
        for(int i=1;i<n;i++) 
        {   
            for(int j=i+1;j<=n;j++)
                map[i][j]=map[j][i]=dkr(t[i][0],t[i][1],t[j][0],t[j][1]);
            map[i][i]=inf;
        }
         scanf("%d",&m);
         while(m--) 
         {
            scanf("%d%d",&a,&b);
            map[a][b]=map[b][a]=0;
         }
         prim();
    return 0;
}

2.并查集

#include<cstdio>
#include<algorithm>
#include<cmath>
#define len 750
using namespace std;
int use[len],t[len][2];
struct node
{
    int x,y;
    double l;
}s[len*400];
int com(node a,node b)
{
    return a.l<b.l;
}
int find(int x)
{
    return x!=use[x]? use[x]=find(use[x]):x;
}
double dkr(int x1,int y1,int x2,int y2)
{
    return sqrt(1.0*(x1-x2)*(x1-x2)+1.0*(y1-y2)*(y1-y2));
}
int main()
{
    int n,m,a,b;
    scanf("%d",&n);
        int k=0;
        for(int i=0;i<=n;i++) use[i]=i;
        for(int i=1;i<=n;i++) scanf("%d %d",&t[i][0],&t[i][1]);
        for(int i=1;i<=n-1;i++)
         for(int j=i+1;j<=n;j++) 
         {
            s[k].x=i;
            s[k].y=j;
            s[k++].l=dkr(t[i][0],t[i][1],t[j][0],t[j][1]);
         }
        sort(s,s+k,com);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d",&a,&b);
            int x=find(a),y=find(b);
            use[y]=x;
        }
        for(int i=0;i<k;i++)
        {
            int x=find(s[i].x),y=find(s[i].y);
            if(x!=y)
            {
                use[y]=x;
                printf("%d %d\n",s[i].x,s[i].y);
            }
        }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值