九度OJ 题目1028:继续畅通工程

来源:互联网 发布:单片机如何烧录程序 编辑:程序博客网 时间:2024/05/30 04:07
一.题目描述:
    省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。
输入:
    测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。

    当N为0时输入结束。
输出:
    每个测试用例的输出占一行,输出全省畅通需要的最低成本。

样例输入:

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
样例输出:

3
1
0

二.题目分析

  还是畅通工程,以不变应万变才是生存之道,不变的是并查集加kruskal,唯一需要应变的是当道路已经修建,那么代价为0,真的是太机智了。

三.代码

#include <stdio.h>#include <stdlib.h>#define MAX 5000int set[100],N;typedef struct edge{    int v1,v2,w,status;}Edge;Edge e[MAX];int FindRoot(int v){    while(v!=set[v])        v=set[v];    return v;}int cmp(const void*a,const void*b){    return (*(Edge*)a).w-(*(Edge*)b).w;}void Kruskal(){    int i,j,cost=0,r1,r2,cn=0;    qsort(e,N*(N-1)/2,sizeof(e[0]),cmp);    for(i=0;i<N*(N-1)/2;i++)    {        r1=FindRoot(e[i].v1);        r2=FindRoot(e[i].v2);        if(r1!=r2)        {            set[r1]=r2;            cost +=e[i].w;            cn++;            if(cn==N-1)                break;        }    }    printf("%d\n",cost);}int main(){    int i;    while(1)    {        scanf("%d",&N);        if(N==0)            break;        for(i=1;i<=N;i++)            set[i]=i;        for(i=0;i<N*(N-1)/2;i++)        {            scanf("%d%d%d%d",&e[i].v1,&e[i].v2,&e[i].w,&e[i].status);            if(e[i].status==1)     //核心改变                e[i].w=0;        }        Kruskal();    }    return 0;}


0 0