1. 程式人生 > 實用技巧 >【Uva1151】Buy or Build

【Uva1151】Buy or Build

https://vjudge.net/problem/UVA-1151

題意:給n個點,連線點i和點j的邊的花費為兩點的歐幾里得距離,有q套構成,可以直接使用對應的花費將套餐中的點加入生成樹,也可以直接建邊,求最小生成樹。

思路:先對n個點進行一次Kruskal,之後對套餐的選中與否進行狀態壓縮,遍歷所有情況即可。

  1 #include <bits/stdc++.h>
  2 #define fi first
  3 #define se second
  4 #define pb(i) push_back(i)
  5 #define rep(i, a, b) for (int i = a; i <= b; i++)
  6
#define per(i, a, b) for (int i = b; i >= a; i--) 7 #define mem(a, b) memset(a, b, sizeof(a)) 8 #define VI vector<int> 9 #define VLL vector<ll> 10 #define MPII map<pair<int, int>, int> 11 #define mp make_pair 12 #define PQI priority_queue<int> 13 #define lowbit(x) x & -x 14
#define debug(a) cout << #a << '=' << a << '\n' 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int N = 1e6 + 10; 19 const int INF = 0x3f3f3f3f; 20 const int inf = -INF; 21 const int mod = 1e9 + 7; 22 const double pi = acos(-1.0
); 23 const double eps = 1e-5; 24 25 int n, q; 26 int p[1005]; 27 int x[1005], y[1005]; 28 vector<int> subn[10]; 29 int cost[10]; 30 int find(int x) 31 { 32 return p[x] == x ? x : p[x] = find(p[x]); 33 } 34 struct Edge 35 { 36 int u, v, d; 37 Edge(int u, int v, int d) : u(u), v(v), d(d){}; 38 bool operator<(const Edge T) const 39 { 40 return d < T.d; 41 } 42 }; 43 int Kruskal(int cnt, vector<Edge> &e, vector<Edge> &res) 44 { 45 if (cnt == 1) 46 return 0; 47 int m = e.size(); 48 int ans = 0; 49 res.clear(); 50 for (int i = 0; i < m; i++) 51 { 52 int u = find(e[i].u), v = find(e[i].v); 53 if (u != v) 54 { 55 ans += e[i].d; 56 p[v] = u; 57 res.push_back(e[i]); 58 if (--cnt == 1) 59 break; 60 } 61 } 62 return ans; 63 } 64 int main() 65 { 66 int T; 67 scanf("%d", &T); 68 while (T--) 69 { 70 scanf("%d%d", &n, &q); 71 for (int i = 0; i < q; i++) 72 { 73 int k; 74 scanf("%d%d", &k, &cost[i]); 75 subn[i].clear(); 76 for (int u, j = 0; j < k; j++) 77 { 78 scanf("%d", &u); 79 subn[i].push_back(u - 1); 80 } 81 } 82 for (int i = 0; i < n; i++) 83 scanf("%d%d", &x[i], &y[i]); 84 vector<Edge> e, need; 85 for (int i = 0; i < n; i++) 86 { 87 for (int j = i + 1; j < n; j++) 88 { 89 int d = (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]); 90 e.push_back(Edge(i, j, d)); 91 } 92 } 93 for (int i = 0; i < n; i++) 94 p[i] = i; 95 sort(e.begin(), e.end()); 96 int ans = Kruskal(n, e, need); 97 for (int mask = 0; mask < (1 << q); mask++) 98 { 99 for (int i = 0; i < n; i++) 100 p[i] = i; 101 int cnt = n, c = 0; 102 for (int i = 0; i < q; i++) 103 { 104 if (mask & (1 << i)) 105 { 106 c += cost[i]; 107 for (int j = 1; j < subn[i].size(); j++) 108 { 109 int u = find(subn[i][j]), v = find(subn[i][0]); 110 if (u != v) 111 { 112 p[v] = u; 113 cnt--; 114 } 115 } 116 } 117 } 118 vector<Edge> res; 119 ans = min(ans, c + Kruskal(cnt, need, res)); 120 } 121 printf("%d\n", ans); 122 if(T) printf("\n"); 123 } 124 system("pause"); 125 return 0; 126 }