08-图7 公路村村通

来源:互联网 发布:java中接口作为参数 编辑:程序博客网 时间:2024/04/27 16:09

最小生成树问题,直接用prim算法就好。

关于prim算法和Dijkstra算法,真心超级像,dijkstra算法中,dis为节点到源点s的距离,所以在每次更新的时候都要把之前累加的距离与这次的权重相加;prim算法,dis指的是到树的最短距离,所以每次更新的时候,只要将权重写进去了。


呃,写的清楚点,是这样 对dijkstra算法(假设s连着x1,x2,x1连着x3,x2连着x4),它的table:

            know  dis  pre   

s          1           0     -1        首先是s被读取,然后它的know被写1,接着更新所有s的邻接点,x1,的dis是2,x2的dis是4,x3和x4的dis还是∞(因为还没被更新过)

x1         1          2      0         接着遍历table,找know为0,且最小的dis,x1弹出来,同样更新x3,的dis为2+1,那么知道x3到x1的距离是1,(注意dis是x3到s的距离)

x2         0           4       0      然后依次类推……

x3         1           3        1

x4         0           ∞         -1    

……

prim算法就是在上述的基础上,将更新这一步变成不加前一节点的dis,直接把权重给过去


#include <stdio.h>#include <stdlib.h>typedef struct _con{int name;int price;struct _con *next;}Con;typedef struct _head{struct _con *head;}Head;typedef struct _table{int know;int pri;int pre;}Table;int Country;int Road;Head *ArrayList;Table *Sheet;void add_array(Con *Beginer,int name,int price);void print_list(Con *Beginer);void prim();int  find_min();void print_table();int main(){scanf("%d %d",&Country,&Road);ArrayList=(Head*)malloc((Country+1)*sizeof(Head));Sheet=(Table*)malloc((Country+1)*sizeof(Table));int i,j,p,k;for(k=0;k<Country+1;k++){ArrayList[k].head=(Con*)malloc(sizeof(Con));ArrayList[k].head->next=NULL;Sheet[k].pri=10000;Sheet[k].know=0;Sheet[k].pre=-1;}for(k=0;k<Road;k++){scanf("%d %d %d",&i,&j,&p);add_array(ArrayList[i].head,j,p);add_array(ArrayList[j].head,i,p);}//for(k=1;k<Country+1;k++){//printf("The %d\t",k);//print_list(ArrayList[k].head);//printf("\n");//}prim();//print_table();int cnt;int result=0;for(k=1,cnt=0;k<Country+1;k++){if(Sheet[k].know==1){cnt++;result=result+Sheet[k].pri;}}if(cnt==Country){printf("%d",result);}else{printf("-1");}return 0;}void add_array(Con *Beginer,int name,int price){Con *p=Beginer;Con *q=(Con*)malloc(sizeof(Con));q->name=name;q->price=price;q->next=p->next;Beginer->next=q;}void prim(){Sheet[1].pri=0;Sheet[1].pre=0;int record;Con *subhead;while(1){record=find_min();Sheet[record].know=1;if(record==-1){break;}subhead=ArrayList[record].head->next;while(subhead){if(Sheet[subhead->name].know==0){if(Sheet[subhead->name].pri > subhead->price){Sheet[subhead->name].pri = subhead->price;Sheet[subhead->name].pre = record;}}subhead=subhead->next;}}}void print_list(Con *Beginer){Con *p=Beginer->next;while(p){printf("name=%d\tprice=%d\t",p->name,p->price);p=p->next;}}int  find_min(){int result=-1;int price=10000;int k;for(k=1;k<Country+1;k++){if(Sheet[k].know==0){if(Sheet[k].pri<price){result=k;price=Sheet[k].pri;}}}return result;}void print_table(){int k;for(k=1;k<Country+1;k++){printf("%d: know=%d pri=%d pre=%d\n",k,Sheet[k].know,Sheet[k].pri,Sheet[k].pre);}}


08-图7 公路村村通   (30分)

现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式:

输入数据包括城镇数目正整数N1000)和候选道路数目M3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。

输出格式:

输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出1,表示需要建设更多公路。

输入样例:

6 151 2 51 3 31 4 71 5 41 6 22 3 42 4 62 5 22 6 63 4 63 5 13 6 14 5 104 6 85 6 3

输出样例:

12
0 0