(Hdu step 6.1.7) Connect the Cities (when some roads have been built, find the minimum cost for connecting n points), hdu6.1.7
Question:
Connect the Cities |
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) |
Total Submission (s): 391 Accepted Submission (s): 139 |
|
Problem DescriptionIn 2100, since the sea level rise, most of the cities disappear. though some have ved 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. |
InputThe 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 attached ved 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. |
OutputFor each case, output the least money you need to take, if it's impossible, just output-1. |
Sample Input16 4 31 4 22 6 12 3 53 4 332 1 22 1 33 4 5 6 |
Sample Output1 |
Authordandelion |
SourceHDOJ Monthly Contest-2010.04.04 |
Recommendlcy |
Question Analysis:
Calculates the Minimum Spanning Tree. Use kruscal to solve the problem. After all, kruscal is applicable to sparse graphs, and this question may be a little more. Use prim instead and submit it in C ++. (The Hangzhou power server feels like it is a little bit recently... For the same code, the first transaction is TLE (> 1000 ms), and the second transaction is 493 ms. Is this a little more difference. This will cause people to crash ...).
Note:
For example:
16 4 31 4 22 6 12 3 53 4 332 1 22 1 33 4 5 6
From "2 1 2", it is the data that has been created. The idea is that the path between point 1 and point 2 has been established. The following figure shows that the roads between points 1 and 3 have been built,
In the following section, we will connect point 4 to point 5 to point 6.
The Code is as follows:
/** G1.cpp ** Created on: March 10, 2015 * Author: Administrator */# include <iostream> # include <cstdio> # include <string> using namespace std; const int maxn = 501; const int inf = 999999; int map [maxn] [maxn]; bool p [maxn]; int dis [maxn]; int pre [maxn]; int n; int prim () {int sum = 0; int I; for (I = 2; I <= n; ++ I) {p [I] = false; dis [I] = map [1] [I]; pre [I] = 1;} dis [1] = 0; p [1] = true; pre [1] = 1; for (I = 1; I <= n- 1; ++ I) {int min = inf; int k = 0; int j; for (j = 1; j <= n; ++ j) {if (! P [j] & dis [j] <min) {// dis [j] = min; min = dis [j]; k = j ;}} if (k = 0) {// No vertex can be expanded, the graph is not connected, and the Minimum Spanning Tree return-1 cannot be obtained; // return-1 directly .} sum + = dis [k]; p [k] = true; for (j = 1; j <= n; ++ j) {if (! P [j] & dis [j]> map [k] [j]) {dis [j] = map [k] [j]; pre [j] = k ;}}return sum;} int main () {int t; scanf ("% d", & t); int tmp [maxn]; while (t --) {int m, k; scanf ("% d", & n, & m, & k); int I, j; for (I = 1; I <= n; ++ I) {for (j = 1; j <= n; ++ j) {if (I = j) {map [I] [j] = 0 ;}else {map [I] [j] = inf ;}}for (I = 1; I <= m; ++ I) {int a, B, c; scanf ("% d", & a, & B, & c ); if (map [a] [B]> c) {map [a] [B] = map [B] [a] = c ;}} // process the created data. (Note that the format is not the same as that given in the previous question) for (I = 1; I <= k; ++ I) {int size; scanf ("% d", & size); // int tmp [size]; for (j = 0; j <size; ++ j) {scanf ("% d", & tmp [j]) ;}for (j = 0; j <size-1; ++ j) {map [tmp [j] [tmp [j + 1] = 0; map [tmp [j + 1] [tmp [j] = 0 ;}} printf ("% d \ n", prim (); // printf ("% d \ n", prim1 ();} return 0 ;}
The following is the version of the TLE using kruscal:
/** G. cpp ** Created on: March 10, 2015 * Author: Administrator */# include <iostream> # include <cstdio> # include <algorithm> # include <vector> using namespace std; const int maxn = 505; struct Edge {int begin; int end; int weight;} edges [maxn * maxn]; int father [maxn]; int n; int find (int a) {if (a = father [a]) {return a;} return father [a] = find (father [a]);} int kruscal (int count) {int I; for (I = 1; I <= n; ++ I) {fathe R [I] = I;} int counter = 0; int sum = 0; for (I = 1; I <= count; ++ I) {if (counter = N-1) {break;} int fa = find (edges [I]. begin); int fb = find (edges [I]. end); if (fa! = Fb) {father [fa] = fb; sum + = edges [I]. weight; counter ++; }}// printf ("% d \ n", counter); return sum;} bool cmp (Edge a, Edge B) {return. weight <B. weight;} int main () {int t; scanf ("% d", & t); int tmp [maxn]; while (t --) {int m, k; scanf ("% d", & n, & m, & k); int cnt = 1; int I; for (I = 1; I <= m; ++ I) {scanf ("% d", & edges [cnt]. begin, & edges [cnt]. end, & edges [cnt ++]. weight) ;}for (I = 1; I <= k; ++ I) {int size; scanf ("% d", & size ); // int tmp [size]; // vector <int> tmp; int j; for (j = 0; j <size; ++ j) {scanf ("% d", & tmp [j]) ;}for (j = 0; j <size-1; ++ j) {edges [cnt]. begin = tmp [j]; edges [cnt]. end = tmp [j + 1]; edges [cnt ++]. weight = 0 ;}} cnt-= 1; sort (edges + 1, edges + 1 + cnt, cmp); printf ("% d \ n ", kruscal (cnt);} return 0 ;}
If you are not familiar with the prim algorithm, you can use this exercise. It is a bare question for finding the Minimum Spanning Tree:
Http://www.sdutacm.org/sdutoj/problem.php? Action = showproblem & problemid = 2144
The AC code for this question is:
/** T. cpp ** Created on: March 10, 2015 * Author: Administrator */# include <iostream> # include <cstdio> # include <cstring> using namespace std; const int maxn = 101; const int inf = 99999; int map [maxn] [maxn]; bool p [maxn]; int dis [maxn]; int pre [maxn]; int n, m; int prim () {int sum = 0; int I; for (I = 2; I <= n; ++ I) {p [I] = false; dis [I] = map [1] [I]; pre [I] = 1;} p [1] = true; dis [1] = 0; for (I = 1; I <= n-1; ++ I) {I Nt min = inf; int k = 0; int j; for (j = 1; j <= n; ++ j) {if (! P [j] & dis [j] <min) {min = dis [j]; k = j ;}} if (k = 0) {return-10 ;} sum + = dis [k]; p [k] = true; for (j = 1; j <= n; ++ j) {if (! P [j] & dis [j]> map [k] [j]) {dis [j] = map [k] [j]; pre [j] = k ;}}return sum;} int main () {while (scanf ("% d", & n, & m )! = EOF) {// memset (map, inf, sizeof (map); memset (p, false, sizeof (p); int I; int j; for (I = 1; I <= n; ++ I) {for (j = 1; j <= n; ++ j) {if (I = j) {map [I] [j] = 0 ;}else {map [I] [j] = inf ;}}for (I = 1; I <= m; ++ I) {int a, B, c; scanf ("% d", & a, & B, & c ); if (map [a] [B]> c) {map [a] [B] = map [B] [a] = c ;}} printf ("% d \ n", prim ();} return 0 ;}