题意:有n个城市,你可以在城市中建立发电站,或者连接到其它有电的城市,使得所有城市都有电。让你算出完成这个工程的最小费用。
思路:抽象一下问题,发现难点在于我们不知道改在哪几个城市建立发电站,这时候就要用到“超级源点”的技巧了(看了大佬的题解我才知道的...)。
我们虚构出一个点 X ,并且 X 和所有的城市都有连接路径,路径长度就是 建造发电站 的费用。
这样,问题就转变成为了最小生成树了。
//#pragma comment(linker, "/STACK:1024000000,1024000000") //#pragma GCC optimize(2) #include <bits/stdc++.h> using namespace std; typedef double dou; typedef long long ll; typedef pair<int, int> pii; typedef map<int, int> mii; #define pai acos(-1.0) #define M 1000500 #define inf 0x3f3f3f3f #define mod 1000000007 #define IN inline #define W(a) while(a) #define lowbit(a) a&(-a) #define left k<<1 #define right k<<1|1 #define lson L, mid, left #define rson mid + 1, R, right #define ms(a,b) memset(a,b,sizeof(a)) #define Abs(a) (a ^ (a >> 31)) - (a >> 31) #define random(a,b) (rand()%(b+1-a)+a) #define false_stdio ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) ll n; ll cnt; ll boss[2005], x[2005], y[2005], k[2005]; struct Data { ll u, v, w; }edge[M<<2]; set<int>built; vector<pii>load; int find(int t) { if (boss[t] == t)return t; return boss[t] = find(boss[t]); } int main() { false_stdio; cin >> n; for (int i = 0; i <= n; i++)boss[i] = i; for (int i = 1; i <= n; i++)cin >> x[i] >> y[i]; for (int i = 1,c; i <= n; i++) { cin >> c; edge[++cnt] = Data{ 0,i,c }; } for (int i = 1; i <= n; i++)cin >> k[i]; for (int i = 1; i < n; i++) { for (int j = i + 1; j <= n; j++) { ++cnt; edge[cnt].u = i; edge[cnt].v = j; edge[cnt].w = (abs(x[i] - x[j]) + abs(y[i] - y[j])) * (k[i] + k[j]); } } sort(edge + 1, edge + cnt + 1, [](Data& a, Data& b) {return a.w < b.w; }); ll ans = 0; for (int i = 1; i <= cnt; i++) { if (edge[i].w < 0)break; int u = edge[i].u; int v = edge[i].v; int w = edge[i].w; int fu = find(u), fv = find(v); if (fu == fv)continue; boss[fu] = fv; ans += w; if (u == 0)built.insert(v); else load.push_back(pii(u, v)); } cout << ans << endl; cout << built.size() << endl; for (auto iter : built)cout << iter << ' '; cout << endl; cout << load.size() << endl; for (auto iter : load) { cout << iter.first << ' ' << iter.second << endl; } return 0; }