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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章