【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 }

 

posted @ 2020-11-27 22:48  Obake  阅读(122)  评论(0编辑  收藏  举报