cf 【并查集】

http://codeforces.com/contest/1245/problem/D

题意就是:你需要让所有城市都有电,你看也在该城市建电站使他有电,同时你可以链接他与其他城市,使之有电

解决:

我们可以吧每个城市自己建电站以及自己与其他城市的费用用结构体存起来,排个序,再用并查集连起来。

#include<bits/stdc++.h>
#define numm ch-48
#define pd putchar(' ')
#define pn putchar('\n')
#define pb push_back
#define debug(args...) cout<<#args<<"->"<<args<<endl
#define bug cout<<"************"
using namespace std;
template <typename T>
void read(T &res) {
    bool flag=false;char ch;
    while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
    for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
    flag&&(res=-res);
}
template <typename T>
void write(T x) {
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
typedef long long ll;
typedef long double ld;
const int maxn=2000+10;
const ll mod=1e9+7;
const int inf=0x3f3f3f3f;
const double alpha=0.7;
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
struct node {
    int u,v;
    ll w;
    node(){}
    node(int u,int v,ll w):u(u),v(v),w(w){}
    bool operator<(const node&a) {
        return w<a.w;
    }
}e[maxn*maxn+maxn];
struct a {
    ll x,y;
    int pos;
}a[maxn];
ll c[maxn],k[maxn];
int f[maxn];
vector<int >vec1;
vector<pii >vec2;
int getf(int v) {
    return f[v]==v?v:f[v]=getf(f[v]);
}
int main()
{
    int n;
    read(n);
    for(int i=1;i<=n;i++)
        f[i]=i;
    for(int i=1;i<=n;i++) {
        read(a[i].x),read(a[i].y);
//        a[i].pos=i;
    }
    for(int i=1;i<=n;i++)
        read(c[i]);
    for(int i=1;i<=n;i++)
        read(k[i]);
    int cnt=0;
    for(int i=1;i<=n;i++){
        e[++cnt]=node(0,i,c[i]);
        for(int j=i+1;j<=n;j++)
            e[++cnt]=node(i,j,(k[i]+k[j])*(abs(a[i].x-a[j].x)+abs(a[i].y-a[j].y)));
    }
    sort(e+1,e+1+cnt);
    int num=0;
    ll sum=0;
    for(int i=1;i<=cnt;i++){
        int u=e[i].u,v=e[i].v;
        int a=getf(u);
        int b=getf(v);
        if(a!=b){//父亲不同才需要计算,例如你三个点肯定三条边构架出个三角形,但实际上只需要其中两条边就行了,第三条肯定是会被认出有共同父亲的
            f[b]=a;
            if(u==0)
                vec1.pb(v);
            else {
                vec2.pb(mp(u,v));
            }
            num++;//无论你是自己建基站还是连接,因为连接就是默认前面那个已经有电,都只加一个
            sum+=e[i].w;
            if(num==n) break;//保证了要n个城市都亮
        }
    }
    write(sum);pn;
    write(vec1.size());pn;
    if(vec1.size()) {
        for(int i=0;i<vec1.size();i++)
            write(vec1[i]),pd;
        pn;
    }
    write(vec2.size());pn;
    if(vec2.size()) {
        for(int i=0;i<vec2.size();i++)
            write(vec2[i].fi),pd,write(vec2[i].se),pn;;
        pn;
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/hgangang/p/11782335.html