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; }
posted @ 2012-04-19 00:39  等待电子的砹  阅读(539)  评论(0)    收藏  举报