pta题解

pta题解

习题8.4 畅通工程之最低成本建设问题 (30分)

在这里插入图片描述
这题是最小生成树问题,先将费用进行排序,每一次都选取当前最小的费用的那条路,然后用并查集,看看有没有成环,如果没有就将相连的道路进行标记,最后统计是否所有的城镇都连起来了,如果只要一个城镇的主人是自己,那就符合要求。

#include<stdio.h>
int f[10000];
struct way
{
    int a;
    int b;
    int cost;
};
int getf(int v)
{
    if(f[v]==v)
        return v;
    else
    {
        int tmp = getf(f[v]);
		f[v] = tmp;
		return tmp;
    }
}
struct way q[10000];
int main()
{
    struct way t;
    int n,m;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        if(n==0)
            break;
        int i,sum=0,j;
        int num=0;
        for(i=0;i<=m;i++)
        {
            f[i]=i;
        }
        for(i=1;i<=n;i++)
        {
            scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].cost);
        }
        for(i=1;i<=n-1;i++)
        {
            for(j=1;j<=n-i-1;j++)
            {
                if(q[j].cost>q[j+1].cost)
                {
                    t=q[j];
                    q[j]=q[j+1];
                    q[j+1]=t;
                }
            }
        }
        int x,y;
        for(i=1;i<=n;i++)
        {
            x=getf(q[i].a);
            y=getf(q[i].b);
            if(x!=y)
            {
                f[x]=y;
                sum+=q[i].cost;
            }
        }
        for(i=1;i<=m;i++)
        {
            if(f[i]==i)
                num++;
        }
        if(num==1)
            printf("%d\n",sum);
        if(num>1)
            printf("Impossible\n");
    }
}

习题8.5 畅通工程之局部最小花费问题 (35分)

在这里插入图片描述
这题和上面这题很像,但是这题要考虑已经修好的路,一开始在输入的时候,我们就将已经修好的路进行标记,然后将还没修好路费用进行排序,然后跟刚刚一样,选取一条路,先判断有没有成环了,没有就进行标记,然后算进总费用。

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
struct way
{
    int a;
    int b;
    int cost;
    int t;
};
int f[50000];
int getf(int v)
{
    if(v==f[v])
        return v;
    else
    {
        f[v]=getf(f[v]);
        return f[v];
    }
}
void mer(int x,int y)
{
    int f1=getf(x);
    int f2=getf(y);
    if(f1!=f2)
    {
        f[f1]=f2;
    }
}
int cmp(way a,way b)
{
    return a.cost<b.cost;
}
int main()
{
    struct way q[50000];
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)
            break;
            int i;
        for(i=0;i<=n;i++)
        {
            f[i]=i;
        }
        int k=n*(n-1)/2;
        int j=0;
        int x1,x2,x3,x4;
        for(i=0;i<k;i++)
        {
            scanf("%d%d%d%d",&x1,&x2,&x3,&x4);
            {
                if(x4==1)
                {
                    mer(x1,x2);
                }
                else
                {
                    q[j].a=x1;
                    q[j].b=x2;
                    q[j].cost=x3;
                    j++;
                }
            }
        }
        sort(q,q+j,cmp);
        int flag=0,sum=0;
        for(i=0;i<j;i++)
        {
            if(getf(q[i].a)!=getf(q[i].b))
            {
                f[getf(q[i].a)]=f[getf(q[i].b)];
                sum=sum+q[i].cost;
            }
        }
        printf("%d\n",sum);

    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值