hdu 3371 Connect the Cities【MST】

来源:互联网 发布:mybatis 多个数据库 编辑:程序博客网 时间:2024/05/02 04:47

Connect the Cities

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


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
16 4 31 4 22 6 12 3 53 4 332 1 22 1 33 4 5 6
 

Sample Output
1

题目大意:2100年的时候,因为水位上涨,很多城市已经失去了联系,但是还有一部分还在联系,government想要重新把所有的城市都链接起来,但是链接起来需要花费,问最小花费、很明显的最小生成树的题目 。这里特殊的一点就是如果不能完成工作要输出-1的部分,一会着重说明一下、

首先我们需要对仍然链接的city先链接上:

        for(int i=0;i<k;i++)//k个关系        {            int num,pos;            scanf("%d%d",&num,&pos);            for(int j=0;j<num-1;j++)            {                int po;                scanf("%d",&po);                merge(pos,po);            }        }
然后是sort、并且连接未连接的city、这里用c++里边的sort会超时,要用qsort才行、另外我这份代码因为判断-1的时候稍微复杂些,有时候交会AC,但是有的时候会TLE,亲测,交4发AC3发0.0

        int output=0;        qsort(a,m,sizeof(path),cmp);        for(int i=0;i<m;i++)        {            if(find(a[i].x)!=find(a[i].y))            {                merge(a[i].x,a[i].y);                output+=a[i].val;            }        }
最后是判断-1的情况,怎么算作-1呢?有点没有连接上、其实也可以这样理解:所有点不在一个并查集中,所以我们就可以这样来判断

        int flag=0;        int c=find(1);        for(int i=1;i<=n;i++)        {            if(find(i)!=c)//如果不相等相当于就有两个以上的并查集了            flag=1;        }        if(flag==0)        printf("%d\n",output);        else        {            printf("-1\n");//这个时候输出-1        }

最后上完整的不一定交几次AC的TLEorAC代码:(听起来好挫)

#include<stdio.h>#include<string.h>#include<algorithm>#include<stdlib.h>using namespace std;int f[5000];struct path{    int x,y,val;}a[1010101];int b[10100];int cmp(const void * a, const void * b){    return ((path *)a)->val - ((path *)b)->val;}int find(int x){    return f[x] == x ? x : (f[x] = find(f[x]));}void merge(int a,int b){    int A,B;    A=find(a);    B=find(b);    if(A!=B)    f[B]=A;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,m,k;        scanf("%d%d%d",&n,&m,&k);        for(int i=1;i<=n;i++)        {            f[i]=i;        }        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].val);        }        for(int i=0;i<k;i++)        {            int num,pos;            scanf("%d%d",&num,&pos);            for(int j=0;j<num-1;j++)            {                int po;                scanf("%d",&po);                merge(pos,po);            }        }        int output=0;        qsort(a,m,sizeof(path),cmp);        for(int i=0;i<m;i++)        {            if(find(a[i].x)!=find(a[i].y))            {                merge(a[i].x,a[i].y);                output+=a[i].val;            }        }        int flag=0;        int c=find(1);        for(int i=1;i<=n;i++)        {            if(find(i)!=c)            flag=1;        }        if(flag==0)        printf("%d\n",output);        else        {            printf("-1\n");        }    }}





0 0