数据结构_习题8.4 畅通工程之最低成本建设问题_习题8.5 畅通工程之局部最小花费问题

  • 题目分析:最小生成树问题,解法采取了Kruskal算法,利用qsort和并查集实现。8.5在8.4的基础上稍作调整即可。
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;

typedef struct path{
    int val;
    int town1,town2;
}path;
typedef path *pap;

int cmp(const void *a,const void *b){
    pap p1=*(pap *)a,p2=*(pap *)b;
    return p1->val - p2->val;
}

int townG[1001];            //记录Group
int findG(int id){              //根或裸节点
    if(townG[id]<=0) return id; 
    else return townG[id]=findG(townG[id]); //路径压缩
}
void unionG(int id1,int id2){   //仅处理根或裸节点
    townG[id1]+=townG[id2];
    townG[id2]=id1;
}

int main()
{
    int n,m;
    pap P[3000];
    scanf("%d %d",&n,&m);
    for (int i = 0; i < m; i++){
        P[i]=(pap)malloc(sizeof(path));
        scanf("%d %d %d",&P[i]->town1,&P[i]->town2,&P[i]->val);
    }
    qsort(P,m,sizeof(pap),cmp);

    memset(townG,-1,sizeof(townG));
    int pi=0,cost=0,useP=0;
    while (pi<m && useP!=n-1)
    {
        pap tmp=P[pi++];
        int id1=findG(tmp->town1), id2=findG(tmp->town2);//均需转换成根节点(townG[id]小于0,或等于0)。
        if(id1!=-1 && id1==id2) continue;//非裸,且同一个集合
        
        if(townG[id1]<townG[id2]) unionG(id1,id2);
        else unionG(id2,id1);
        cost+=tmp->val,useP++;
    }
    if(useP==n-1) printf("%d",cost);
    else printf("Impossible");

    return 0;
}
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;

typedef struct path{
    int val;
    int town1,town2;
    int state;
}path;
typedef path *pap;

int cmp(const void *a,const void *b){
    pap p1=*(pap *)a,p2=*(pap *)b;
    return p1->val - p2->val;
}

int townG[101];             //记录Group
int findG(int id){              //找根或裸节点
    if(townG[id]<0) return id; 
    else return townG[id]=findG(townG[id]); //路径压缩
}
void unionG(int id1,int id2){   //处理根或裸节点
    townG[id1]+=townG[id2];
    townG[id2]=id1;
}

int pi=0,cost=0,useP=0;       //通过pi使用P,成本记录,联通的路径数目
int updateG(int id1,int id2); //并查集,同个集合返0,新联通返1

int main()
{
    int n;
    pap P[5000];
    scanf("%d",&n);
    int pn=(n*(n-1))/2;
    memset(townG,-1,sizeof(townG));
    for (int i = 0; i < pn; i++){
        P[i]=(pap)malloc(sizeof(path));
        scanf("%d %d %d %d",&P[i]->town1,&P[i]->town2,&P[i]->val,&P[i]->state);
        if(P[i]->state==1) updateG(P[i]->town1,P[i]->town2);
    }
    qsort(P,pn,sizeof(pap),cmp);

    while (pi<pn && useP!=n-1)
    {
        pap tmp=P[pi++];

        if(tmp->state==0) //可能需要联通
        {   
            int flag=updateG(tmp->town1,tmp->town2);
            if(flag==1) cost+=tmp->val;
        }
    }
    if(useP==n-1) printf("%d",cost);
    else printf("Impossible");

    return 0;
}
int updateG(int id1,int id2)
{
    id1 = findG(id1), id2 = findG(id2);
    if (id1 != -1 && id1 == id2) return 0; //非裸,且同一个集合

    useP++;                                //有效路径+1
    if (townG[id1] < townG[id2]) unionG(id1, id2);
    else unionG(id2, id1);

    return 1;
}

posted @   kingdalf  阅读(20)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示