hdu_3371 Connect the Cities

来源:互联网 发布:淘宝如何打开淘口令 编辑:程序博客网 时间:2024/06/08 06:36

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3371

分析:

       题目大意:有n个城市,你可以链接的城市有m对。通过k条输入,可以知道哪些城市是连通的。要求使用最少的花费将所有城市连通起来,如果不能连起来则输出-1,能则输出最小花费。

      如下图,通过最后面的k行输入可得下图连通关系。

    由m,我们可以知道我们能连接的城市即花费。

     城市   城市  花费

      1          4         2

      2          6         1

      2          3         5

      3          4        33

所以,为使城市连通又要花费少,我们连接2,6;


      算法分析:使用并查集+贪心。连通的城市在一个集合里,对m条可以连接的边安费用从小到大排序。对m连接的连个城市做判断,如果在同一集合则不用连通,不再同一集合,就把集合合并,记录此时花费。m条边判断完后,看是否只有一个集合,是的话则意味着所有此时连通了。

我的代码:

#include<stdio.h>#include<algorithm>using namespace std;#define MAXN 505#define MAXM 25005int f[MAXN];int r[MAXM];struct Node{    int p,q,c;    //重定义< 然其按c从小到大排。    bool operator <(const Node &x ) const{        return c<x.c;    }};Node a[MAXM];void init(int n){    for(int i=1;i<=n;i++)    {        f[i]=i;        r[i]=1;    }}int find(int n)  //找n所在集合。{    if(f[n]==n) return n;    else return f[n]=find(f[n]);  //路劲压缩}void Union(int x,int y)  // x所在集合与y所在集合,合并。{    int a=find(x);    int b=find(y);    if(a==b) return ;    else    {        if(r[a]<r[b])   //按秩合并,即将集合元素少得合并到元素多得集合里。        {            f[a]=b;            r[b]+=r[a];        }        else        {            f[b]=a;            r[a]+=r[b];        }    }}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,m,k;        scanf("%d%d%d",&n,&m,&k);        init(n); //初始化,并查集。        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&a[i].p,&a[i].q,&a[i].c);        }        sort(a,a+m);  //对m条边排序。        while(k--)  //用并查集,求出集合。        {            int num,e,e1;            scanf("%d%d",&num,&e);            for(int i=1;i<num;i++) //已经输入了a,少输入一个。            {                scanf("%d",&e1);                Union(e,e1);            }        }        int tot=0; //总花费。        for(int i=0;i<m;i++)  //在 a 数组中选出可用的边链接集合。        {            int ind1=find(a[i].p);            int ind2=find(a[i].q);            if(ind1==ind2) continue;            else            {                tot+=a[i].c;                Union(ind1,ind2);            }        }        int root_num=0;        for(int i=1;i<=n;i++) //判断集合个数        {            if(f[i]==i) root_num++;            if(root_num>1) break;        }        if(root_num>1) //集合个数>1,即城市没有链接。        {            printf("-1\n");        }        else        {            printf("%d\n",tot);        }    }    return 0;}
总结:其实本题还是挺简单的,与食物链那种题目相比。


原创粉丝点击