HDU 畅通工程系列
畅通工程系列都是比较裸的最小生成树问题,且是中文题目,不赘述了。
1、HDU 1863 畅通工程
题意:一个省有很多村庄,其中一些之间是可以建公路的,每条公路都需要不同的代价,问代价最小的情况下将所有村庄都连通。
解法:裸的最小生成树。
tag:MST
由于才学MST,两种算法一个写了一遍:
Kruskal:
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-11-30 10:21 4 * File Name: G-HDU-1863.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <algorithm> 9 10 using namespace std; 11 12 typedef pair<int, int> pii; 13 struct Pat{ 14 int s, e, w; 15 }; 16 17 int n, m, f[110]; 18 Pat p[10005]; 19 20 bool cmp(Pat a, Pat b) 21 { 22 return a.w < b.w; 23 } 24 25 void init() 26 { 27 for (int i = 0; i < n; ++ i){ 28 scanf ("%d%d%d", &p[i].s, &p[i].e, &p[i].w); 29 -- p[i].s; --p[i].e; 30 } 31 } 32 33 int find(int x) 34 { 35 if (x != f[x]) f[x] = find(f[x]); 36 return f[x]; 37 } 38 39 int kruskal(int n, int m) 40 { 41 sort(p, p+m, cmp); 42 for (int i = 0; i < n; ++ i) 43 f[i] = i; 44 int cost = 0; 45 for (int i = 0; i < m; ++ i){ 46 int s = p[i].s, e = p[i].e; 47 int t1 = find(s), t2 = find(e); 48 if (t1 != t2){ 49 f[t1] = t2; 50 cost += p[i].w; 51 } 52 } 53 54 int tmp = find(0); 55 for (int i = 1; i < n; ++ i){ 56 find (i); 57 if (f[i] != tmp) return -1; 58 } 59 return cost; 60 } 61 62 int main() 63 { 64 while (scanf ("%d%d", &n, &m) != EOF && n){ 65 init(); 66 int ans = kruskal(m, n); 67 if (ans == -1) printf ("?\n"); 68 else printf ("%d\n", ans); 69 } 70 return 0; 71 }
Prim:
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-11-30 10:51 4 * File Name: G-HDU-1863.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <cstring> 9 #include <vector> 10 #include <queue> 11 #include <utility> 12 13 using namespace std; 14 15 #define CLR(x) memset(x, 0, sizeof(x)) 16 #define PB push_back 17 const int maxint = 2147483647; 18 typedef pair<int, int> pii; 19 20 int n, m; 21 bool v[110]; 22 int c[110]; 23 vector<pii> p[110]; 24 25 struct cmp{ 26 bool operator() (pii a, pii b){ 27 return a.second > b.second; 28 } 29 }; 30 31 void init() 32 { 33 for (int i = 0; i < n; ++ i) 34 p[i].clear(); 35 36 int a, b, w; 37 for (int i = 0; i < m; ++ i){ 38 scanf ("%d%d%d", &a, &b, &w); 39 -- a; -- b; 40 p[a].PB (make_pair(b, w)); 41 p[b].PB (make_pair(a, w)); 42 } 43 } 44 45 int prim(int n, int m) 46 { 47 int cost = 0; 48 CLR (v); 49 priority_queue<pii, vector<pii>, cmp> q; 50 while (!q.empty()) q.pop(); 51 52 for (int i = 1; i < n; ++ i) 53 c[i] = maxint - 1000; 54 c[0] = 0; 55 v[0] = 1; 56 for (int i = 0; i < (int)p[0].size(); ++ i){ 57 pii tmp = p[0][i]; 58 c[tmp.first] = tmp.second; 59 q.push (make_pair(tmp.first, tmp.second)); 60 } 61 62 for (int i = 0; i < n-1; ++ i){ 63 if (q.empty()) break; 64 pii tmp = q.top(); q.pop(); 65 while (v[tmp.first] && !q.empty()){ 66 tmp = q.top(); q.pop(); 67 } 68 if (v[tmp.first]) break; 69 70 int t1 = tmp.first, t2 = tmp.second; 71 cost += t2; 72 v[t1] = 1; 73 c[t1] = 0; 74 for (int j = 0; j < (int)p[t1].size(); ++ j) if (!v[p[t1][j].first]){ 75 pii t = p[t1][j]; 76 if (c[t.first] > t.second){ 77 q.push (make_pair(t.first, t.second)); 78 c[t.first] = t.second; 79 } 80 } 81 } 82 83 for (int i = 0; i < n; ++ i) 84 if (!v[i]) return -1; 85 return cost; 86 } 87 88 int main() 89 { 90 while (scanf ("%d%d", &m, &n) != EOF && m){ 91 init(); 92 int ans = prim(n, m); 93 if (ans == -1) printf ("?\n"); 94 else printf ("%d\n", ans); 95 } 96 return 0; 97 }
2、HDU 1875 畅通工程再续
没写代码。
3、HDU 1879 继续畅通工程
用Kruskal写了一份:
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-12-01 02:52 4 * File Name: G-HDU-1879.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <algorithm> 9 10 using namespace std; 11 12 struct Pat{ 13 int s, e, w; 14 }; 15 16 int n, all, f[110]; 17 Pat p[10005]; 18 19 bool cmp(Pat a, Pat b) 20 { 21 return a.w < b.w; 22 } 23 24 int find (int x) 25 { 26 if (x != f[x]) f[x] = find(f[x]); 27 return f[x]; 28 } 29 30 void init() 31 { 32 all = 0; 33 for (int i = 0; i < n; ++ i) 34 f[i] = i; 35 36 int s, e, w, x; 37 for (int i = 0; i < n*(n-1)/2; ++ i){ 38 scanf ("%d%d%d%d", &s, &e, &w, &x); 39 -- s; -- e; 40 if (x == 1){ 41 int t1 = find(s), t2 = find(e); 42 if (t1 != t2) f[t1] = t2; 43 } 44 else{ 45 p[all].s = s; p[all].e = e; 46 p[all++].w = w; 47 } 48 } 49 } 50 51 int kruskal() 52 { 53 int cost = 0; 54 sort(p, p+all, cmp); 55 for (int i = 0; i < all; ++ i){ 56 int s = p[i].s, e = p[i].e, w = p[i].w; 57 int t1 = find(s), t2 = find(e); 58 if (t1 != t2){ 59 f[t1] = t2; cost += w; 60 } 61 } 62 return cost; 63 } 64 65 int main() 66 { 67 while (scanf ("%d", &n) != EOF && n){ 68 init(); 69 int ans = kruskal(); 70 printf ("%d\n", ans); 71 } 72 return 0; 73 }
4、HDU 1233 还是畅通工程
用Prim写了一份:
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-12-02 01:43 4 * File Name: G-HDU-1233.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <cstring> 9 #include <algorithm> 10 #include <vector> 11 #include <queue> 12 #include <utility> 13 14 using namespace std; 15 16 #define CLR(x) memset(x, 0, sizeof(x)) 17 #define CLR1(x) memset(x, -1, sizeof(x)) 18 #define PB push_back 19 typedef pair<int, int> pii; 20 21 int n, m, d[110]; 22 bool v[110]; 23 vector<pii> pat[110]; 24 25 struct cmp{ 26 bool operator() (pii a, pii b){ 27 return a.second > b.second; 28 } 29 }; 30 31 void init() 32 { 33 for (int i = 0; i < n; ++ i) 34 pat[i].clear(); 35 36 m = n * (n-1) / 2; 37 int a, b, w; 38 for (int i = 0; i < m; ++ i){ 39 scanf ("%d%d%d", &a, &b, &w); 40 -- a; -- b; 41 pat[a].PB (make_pair(b, w)); 42 pat[b].PB (make_pair(a, w)); 43 } 44 } 45 46 int Prim(int n, int m) 47 { 48 priority_queue<pii, vector<pii>, cmp> q; 49 while (!q.empty()) q.pop(); 50 51 int cost = 0; 52 CLR1 (d); 53 CLR (v); v[0] = 1; d[0] = 0; 54 int t_sz = pat[0].size(); 55 for (int i = 0; i < t_sz; ++ i){ 56 pii tmp = pat[0][i]; 57 d[tmp.first] = tmp.second; 58 q.push (tmp); 59 } 60 61 for (int i = 0; i < n-1; ++ i){ 62 if (q.empty()) break; 63 pii tmp = q.top(); q.pop(); 64 while (v[tmp.first] && !q.empty()){ 65 tmp = q.top(); q.pop(); 66 } 67 if (v[tmp.first]) break; 68 69 int t1 = tmp.first, t2 = tmp.second; 70 cost += t2; v[t1] = 1; d[t1] = 0; 71 int sz = pat[t1].size(); 72 for (int j = 0; j < sz; ++ j) if (!v[pat[t1][j].first]){ 73 pii tt = pat[t1][j]; 74 if (d[tt.first] > tt.second){ 75 q.push (make_pair(tt.first, tt.second)); 76 d[tt.first] = tt.second; 77 } 78 } 79 } 80 81 for (int i = 0; i < n; ++ i) 82 if (!v[i]) return -1; 83 return cost; 84 } 85 86 int main() 87 { 88 while (scanf ("%d", &n) != EOF && n){ 89 init(); 90 int ans = Prim(n, m); 91 printf ("%d\n", ans); 92 } 93 return 0; 94 }
------------------------------------------------------------------
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。