HDU3371 Connect the Cities【Kruskal】

Connect the Cities


Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11152    Accepted Submission(s): 3155

Problem Description
In 2100, since the sea level rise, most of the cities disappear. Though some survived cities are still connected with others, but most of them become disconnected. The government wants to build some roads to connect all of these cities again, but they don’t want to take too much money.  
 
Input
The first line contains the number of test cases.
Each test case starts with three integers: n, m and k. n (3 <= n <=500) stands for the number of survived cities, m (0 <= m <= 25000) stands for the number of roads you can choose to connect the cities and k (0 <= k <= 100) stands for the number of still connected cities.
To make it easy, the cities are signed from 1 to n.
Then follow m lines, each contains three integers p, q and c (0 <= c <= 1000), means it takes c to connect p and q.
Then follow k lines, each line starts with an integer t (2 <= t <= n) stands for the number of this connected cities. Then t integers follow stands for the id of these cities.

Output
For each case, output the least money you need to take, if it’s impossible, just output -1.
 
Sample Input
1
6 4 3
1 4 2
2 6 1
2 3 5
3 4 33
2 1 2
2 1 3
3 4 5 6
 
Sample Output

1


题目大意:首先是T组数据,之后每组第一行是N M K,表示N个城市,M条路的信息,和

已经连接上的K个城市信息。接下来M行每行是城市A到B建路需要的花费。再接下来K行每

行第一个数为t,之后t个数表示已经连接在一起的城市。简单说,就是给你N个城市和M条

路的花费,再给你已经联通的城市,求连接所有城市的最小生成树总权值是多少。

思路:用kruskal算法来做,先把联通的城市并入集合,再依次并入边权值最小的边,直到

并到N-1条边,就生成了最小生成树。如果并完了没有达到N-1条边,就是不能联通,输出

"-1"。这道题昨天写的,提交了23次,不是TLE就是栈溢出,最后发现:把cin改为scanf,

再把sort改为qsort就不超时了。。。前边的我理解,后边的就比较无语了。。。

原来sort用C++提交会超时,G++就不会超时。。。但是不知道原理,求大神解释。。。


AC代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

struct Node
{
    int from;
    int to;
    int w;
}Edges[25500];

int father[550],ans;

int find(int x)
{
    int root = x;
    while(root != father[root])
    {
        root = father[root];
    }

    int z;
    while(x != root)
    {
        z = father[x];
        father[x] = root;
        x = z;
    }
    return root;
}

//bool cmp(Node a,Node b)
//{
//    return a.w < b.w;
//}

int cmp(const void * a, const void * b)
{
    return ((Node *)a)->w - ((Node *)b)->w;
}

bool Kruskal(int N,int M,int k)
{
//    sort(Edges,Edges+M,cmp);
    qsort(Edges,M,sizeof(Node),cmp);
    int x,y;
    for(int i = 0; i < M; i++)
    {
        x = find(Edges[i].from);
        y = find(Edges[i].to);
        if(x != y)
        {
            father[y] = x;
            k++;
            ans += Edges[i].w;
            if(k == N-1)
                return true;
        }
    }
    if(k == N-1)
        return true;
    else
        return false;
}
int main()
{
    int T,k,t,a,b,N,M,K;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&N,&M,&K);
        for(int i = 1; i <= N; i++)
            father[i] = i;
        for(int i = 0; i < M; i++)
        {
            scanf("%d%d%d",&Edges[i].from,&Edges[i].to,&Edges[i].w);
        }
        k = 0,ans = 0;
        for(int i = 0; i < K; i++)
        {
            scanf("%d%d",&t,&a);
            a = find(a);
            t--;
            while(t--)
            {
                scanf("%d",&b);
                b = find(b);
                if(a != b)
                {
                    father[b] = a;
                    k++;
                }
            }
        }

        if(Kruskal(N,M,k))
            printf("%d\n",ans);
        else
            printf("-1\n");
    }

    return 0;
}



你可能感兴趣的:(HDU3371 Connect the Cities【Kruskal】)