HDU 1102
一道最小生成树的问题。
题目所给的输入是按矩阵的方式输入的,显然这个矩阵关于主对角元对称,所以只需要存储一半的数据即可(其实少于一半,主对角元也不用存储)。对于输入所给的已修好路的两个村子,合并它们分别所在的集合(开始的时候思维有漏洞,直接parnt[h]=l,这样是不对的,应该先找到它们的根进行合并,看来自己思维的严密性还是很欠缺)。剩下的直接按照Kruskal算法的思路进行即可,遇到不在同一连通集合的村子,说明两个村子之间需要修路。
#include<stdio.h> #include<stdlib.h> #define max_town 110 #define max_road 10200 struct edge { int a; int b; int v; }edge[max_road]; int get_root(int),cmp(const void *,const void *),parnt[max_road],sum=0; void unon(int,int); int main() { int n; while(scanf("%d",&n)!=EOF) { int i,p=0,q,trash,k; for(i=0,k=0;i<n-1;i++,k++)//输入部分 { int j; for(j=0;j<n;j++) { if(j>=k&&i!=j)//存储主对角元右上方的元素 { edge[p].a=i; edge[p].b=j; scanf("%d",&edge[p].v); p++;//已存个数,方便排序 } else { scanf("%d",&trash); } } } for(i=0;i<n;i++) { scanf("%d",&trash); }//********************************输入结束 for(i=0;i<p;i++)//初始化并查集 parnt[i]=i; qsort(edge,p,sizeof(edge[0]),cmp); scanf("%d",&q); for(i=0;i<q;i++) { int h,l; scanf("%d%d",&h,&l); h--;l--;
/*将已经修通路的村子放入一个连通集合中*/ h=get_root(h); l=get_root(l); parnt[h]=l; } for(i=0;i<p;i++) { if(get_root(parnt[(edge[i].a)])!=get_root(parnt[(edge[i].b)])) { sum+=edge[i].v; unon(edge[i].a,edge[i].b);//修了路之后,将两个村子放入一个连通集合 } } printf("%d\n",sum); sum=0; } return 0; } int get_root(int x) { if(parnt[x]!=x) { parnt[x]=get_root(parnt[x]); } return parnt[x]; } void unon(int x,int y) { x=get_root(x); y=get_root(y); if(x!=y) { parnt[x]=y; } } int cmp(const void *x,const void *y) { return (*(struct edge *)x).v-(*(struct edge *)y).v; }
浙公网安备 33010602011771号