Codeforces Round #597 (Div. 2) D - Shichikuji and Power Grid

题意:有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;
}

猜你喜欢

转载自www.cnblogs.com/caibingxu/p/11783939.html