(思维+最小生成树)Codeforces1245D.Shichikuji and Power Grid

题意:(来源洛谷)

 

 

思路:一个非常巧妙的方法,将在城市i建造发电站看作是将城市i与城市0连接,代价即为ci。其他城市间则按题意建立边,求一次最小生成树即可。需要开long long。

代码:

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll N = 2020;
 5 struct edge{
 6     ll u, v, w;
 7     edge(ll a, ll b, ll c): u(a), v(b), w(c) {}
 8     bool operator < (const edge &x) const {
 9         return w < x.w;
10     }
11 };
12 ll k[N], cost[N], x[N], y[N], f[N];
13 ll n;
14 vector <edge> e;
15 ll find(ll x) {
16     return x == f[x] ? x : f[x] = find(f[x]);
17 }
18 
19 int main()
20 {
21     scanf("%lld", &n);
22     for (ll i = 1; i <= n; i++)
23         scanf("%lld %lld", &x[i], &y[i]);
24     for (ll i = 1; i <= n; i++) scanf("%lld", &cost[i]);
25     for (ll i = 1; i <= n; i++) scanf("%lld", &k[i]);
26     
27     for (ll i = 1; i <= n; i++) e.push_back(edge(0, i, cost[i]));
28     for (ll i = 1; i <= n; i++)
29         for (ll j = 1; j <= n; j++) {
30             if (j <= i) continue;
31             e.push_back(edge(i, j, (k[i]+k[j])*(abs(x[i]-x[j])+abs(y[i]-y[j]))));
32         }
33     sort(e.begin(), e.end());
34     vector <ll> a;
35     vector <edge> used;
36     ll cnt = 0, ans = 0;
37     for (ll i = 0; i <= n; i++) f[i] = i;
38     for (auto it : e) {
39         ll u = find(it.u), v = find(it.v);
40         if (u != v) {
41             ll z = 0;
42             if (z == it.v) a.push_back(it.u);
43             if (z == it.u) a.push_back(it.v);
44             if (z != it.u && z != it.v) used.push_back(it);
45             cnt++; f[u] = v; ans += it.w;
46         }
47         if (cnt == n) break;
48     }
49     cout << ans << endl;
50     cout << a.size() << endl;
51     for (auto it : a) printf("%lld ", it);
52     puts("");
53     cout << used.size() << endl;
54     for (auto it : used) printf("%lld %lld\n", it.u, it.v);
55     return 0;
56 }
View Code

 

 

猜你喜欢

转载自www.cnblogs.com/FantaDevourer/p/13378688.html