hdu3371 Connect the Cities [prim最小生成树模板]

Connect the Cities

hdu3371题目链接

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

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

解题思路

这题就是一个最小生成树得模板题,这里输入一个n,m,k。表示有n个点,m条路并且有对应的权值,k表示有k个已经相连成树的点了,k中每一行任意两点都是想连接好的,求出这个图的最小生成树。

这里我用的是prime算法,在处理k的时候如果用双重循环表示任意两点相连的话就会超时了,这里只能用单循环,把相邻的两个点链接起来就ok了。

昨天写出来的,然后今天早上我又写了一遍的,同样的代码结果就超时了,后来我发现,我是用数组f[550]存的这些点,每次置0都需要花时间的,结果就是一直超时,怎么改都不对。然后我就换了第一种写法就过了。然后我就把f[550]数组改小了,因为大小不会超过n, n(max)=500所以我就开到510了,险过。

1.scanf("%d",&p);
  scanf("%d",&a);
    p--;
    while(p--){                 // 写法1.这里两种写法都不会超时 
        scanf("%d",&b);
        map[a][b]=map[b][a]=0;
        a=b;
    }
2.memset(f,0,sizeof(f));        // 写法2.这里f数组不能开太大,n是500我就只开到510的 
  for(i=0;i<p;i++)
    scanf("%d",&f[i]);
  for(i=0;i<p-1;i++)
    map[f[i]][f[i+1]]=map[f[i+1]][f[i]]=0;

程序代码

#include <stdio.h>
#include <string.h>
#define inf 99999999
int dis[550];
int book[550];
int map[550][550];

int main()
{
    int i,j;
    int f[510];
    int t,n,m,k,p;
    int a,b,u,v,l;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d",&n,&m,&k);
        memset(dis,0,sizeof(dis));
        memset(map,0,sizeof(map));
        memset(book,0,sizeof(book));
        for(i=1;i<=n;i++){
            for(j=1;j<=n;j++)
                map[i][j]=inf;
        }
        for(i=0;i<m;i++){
            scanf("%d%d%d",&u,&v,&l);
            if(l<map[u][v]){
                map[u][v]=map[v][u]=l;
            }
        }
        while(k--){
            scanf("%d",&p);
            scanf("%d",&a);
            p--;
            while(p--){                 // 写法1.这里两种写法都不会超时 
                scanf("%d",&b);
                map[a][b]=map[b][a]=0;
                a=b;
            }
//          memset(f,0,sizeof(f));      // 写法2.这里f数组不能开太大,n是500我就只开到510的 
//          for(i=0;i<p;i++)
//              scanf("%d",&f[i]);
//          for(i=0;i<p-1;i++)
//              map[f[i]][f[i+1]]=map[f[i+1]][f[i]]=0;
        }
        for(i=1;i<=n;i++)
            dis[i]=map[1][i];
        book[1]=1;
        int sum=0;
        for(i=1;i<n;i++){
            int min=inf;
            for(j=1;j<=n;j++){
                if(!book[j]&&dis[j]<min){
                    min=dis[j];
                    u=j;
                }
            }
            sum+=min;
            if(sum>=inf)
                break;
            book[u]=1;
            for(j=1;j<=n;j++){
                if(!book[j]&&dis[j]>map[u][j])
                    dis[j]=map[u][j];
            }
        }
        if(sum>=inf||sum<0)
            printf("-1\n");
        else
            printf("%d\n",sum);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章