hdu1879 继续畅通工程

本文介绍了一个算法问题,旨在计算使所有村庄通过道路相互连接所需的最低成本。利用了Kruskal算法来解决最小生成树问题,并考虑了部分道路可能已建成的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

继续畅通工程

省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。

Input

测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。

N为0时输入结束。

Output

每个测试用例的输出占一行,输出全省畅通需要的最低成本。

Sample Input

3

1 2 1 0

1 3 2 0

2 3 4 0

3

1 2 1 0

1 3 2 0

2 3 4 1

3

1 2 1 0

1 3 2 1

2 3 4 1

0

Sample Output

3

1

0

 

 

#include<algorithm>

#include<cstdio>

#include<cstring>

#include<iostream>

using namespace std;

struct node

{

    int st;

    int ed;

    int val;

    int mark;

}e[5008];//把每条边成为一个结构体,包括起点、终点和权值

int pre[5008];

int n;

int cmp(node a,node b)

{

    return a.val<b.val;//按照价值从小到大排

}

void make()

{

    for(int i=0;i<n;i++)

    {

        pre[i] = i;

    }

    return ;

}//把每个元素初始化

int Find(int m)

{

    if(m==pre[m])

        return m;

    int t=Find(pre[m]);

    pre[m]=t;

    return pre[m];

}//查找一个元素所在的集合,即找到根节点

void Merge(int x,int y)

{

    int fx=Find(x);

    int fy=Find(y);

    if(fx>fy)

        pre[fx]=fy;

    else

        pre[fy]=fx;

}//合并x,y

int kruskal(int l)

{

    int sum=0;

    for(int i=0;i<l;i++)

    {

        if(e[i].mark==0)

        {

            if(Find(e[i].st)!=Find(e[i].ed))//根节点不同

            {

                //printf("%d%d不相连\n",e[i].st,e[i].ed);

                sum+=e[i].val;

                Merge(e[i].st,e[i].ed);//合并

                //printf("%d的根节点是%d\n",e[i].st,Find(e[i].st));

                //printf("%d的根节点是%d\n",e[i].ed,Find(e[i].ed));

                //printf("%d的根节点是%d\n",e[i+1].ed,Find(e[i+1].ed));

            }

        }

    }

    return sum;

}

int main()

{

    while(scanf("%d",&n)!=EOF)

    {

        if(n==0)

            break;

        make();

        for(int i=0;i<n*(n-1)/2;i++)

        {

            scanf("%d%d%d%d",&e[i].st,&e[i].ed,&e[i].val,&e[i].mark);

            if(e[i].mark==1)

            {

                Merge(e[i].st,e[i].ed);

                //printf("%d%d相连\n",e[i].st,e[i].ed);

                //printf("%d的根节点是%d\n",e[i].ed,Find(e[i].ed));

            }

        }

        sort(e,e+n*(n-1)/2,cmp);

        /*for(int i=0;i<n;i++)

        {

            printf("%d %d %d %d\n",e[i].st,e[i].ed,e[i].val,e[i].mark);

        }*/

        cout<<kruskal(n*(n-1)/2)<<endl;

    }

    return 0;

}

 

注意:数组开的大小100*99/2。。。还有全局变量不要与函数里的变量重名。。。还有初始化的位置。。。还有输入问题cin输入超时,scanf输入可以。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值