zoukankan      html  css  js  c++  java
  • Codeforces Round #597 (Div. 2) D

    题意:有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;
    }
  • 相关阅读:
    学习了一下调色理论
    几个同步软件
    慢性咽炎
    flash行情
    C#创建Windows服务
    .net下 foreach 与 for 的效率比较测试
    HTML服务器控件与Web服务器控件的区别
    c#遍历HashTable
    ASP.NET中Server与Request对象的方法
    .net内存回收与Dispose﹐Close﹐Finalize方法
  • 原文地址:https://www.cnblogs.com/caibingxu/p/11783939.html
Copyright © 2011-2022 走看看