CF1245D Shichikuji and Power Grid 题解

题意

有n个城市,需要让它们都有电,有两种方式能使一个城市有电:

  • 在这个城市建造发电站

  • 将这个城市和另一个有电的城市用电缆相连

分析

建立一个超级源点,在 \(i\) 号城市建造发电站可以看成从超级源点向 \(i\) 号点连接了一条权值为 \(c[i]\) 的边,用电缆连接 \(i\) 号城市和 \(j\) 号城市就可以看成在 \(i\) 号城市间连接一条权值为 \((k[i]+k[j])\times(\ \left|{x_i-x_j}\right|+\ \left|{y_i-y_j}\right|)\) , 然后用 kruskal就行。

代码

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define int long long
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=1e9+7;
const ll INF=1e17+7;
const int MAXN=2e3+7;
ll n;
struct node
{
	ll x,y,z;
	node(ll a,ll b,ll c){x=a;y=b;z=c;}
	node(){;}
};
vector<node>a;
ll dis(const node &xx,const node &yy)
{
	ll x1=xx.x,x2=yy.x,y1=xx.y,y2=yy.y;
	return (xx.z+yy.z)*(abs(x1-x2)+abs(y1-y2));
}
struct Edge
{
    int from,to,dis;
    Edge(int a,int b,int c){from=a;to=b;dis=c;}
    Edge(){;}
    friend bool operator < (const Edge &xx,const Edge &yy)
    {
        return xx.dis<yy.dis;
    }
};
vector<Edge>edge;
int fa[MAXN];
void makeSet(int size) 
{
    for(int i=0;i<size;i++) fa[i]=i;
    return;
}
int find(int x) 
{
    if(x!=fa[x])
    {
        fa[x]=find(fa[x]);
    }
    return fa[x];
}
void unionSet(int x,int y)
{
    x=find(x);
    y=find(y);
    fa[x]=y;
}
bool flag;
ll ans;
vector<int>path;
void kruskal()
{
    for(ll i=0;i<edge.size();i++)
    {
        if(find(edge[i].from)==find(edge[i].to))
        {
            flag=true;
            continue;
        }
        ans+=edge[i].dis;
        path.push_back(i);
        unionSet(edge[i].from,edge[i].to);
    }
}
vector<int>ans1;
vector<pair<int,int> >ans2;
signed main()
{
    makeSet(MAXN);
    scanf("%lld",&n);
    ll i,j;
    a.push_back(node{0,0,0});
    for(i=1;i<=n;i++)
    {
        ll x,y;
        scanf("%lld%lld",&x,&y);
        a.push_back(node{x,y,0});
    }
    for(i=1;i<=n;i++)
    {
        ll x;
        scanf("%lld",&x);
        edge.push_back(Edge{0,i,x});
    }
    for(i=1;i<=n;i++)
    {
        ll z;
        scanf("%lld",&z);
        a[i].z=z;
    }
    for(i=1;i<=n;i++)
    {
        for(j=i+1;j<=n;j++)
        {
            edge.push_back(Edge{i,j,dis(a[i],a[j])});
            edge.push_back(Edge{j,i,dis(a[i],a[j])});
        }
    }
    sort(edge.begin(),edge.end());
    kruskal();
    for(i=0;i<path.size();i++)
    {
        int tmp=path[i];
        if(edge[tmp].from==0) ans1.push_back(edge[tmp].to);
        else ans2.push_back(make_pair(edge[tmp].from,edge[tmp].to));
    }
    printf("%lld\n%d\n",ans,ans1.size()); //注意ans1.size()是int类型的,后面的ans2.size()也是 
    sort(ans1.begin(),ans1.end());
    for(i=0;i<ans1.size();i++)
    {
        printf("%lld ",ans1[i]);
    }
    printf("\n");
    printf("%d\n",ans2.size());
    for(i=0;i<ans2.size();i++)
    {
        printf("%lld %lld\n",ans2[i].first,ans2[i].second);
    }
    return 0;
}
posted @ 2022-02-18 11:17  l_x_y  阅读(60)  评论(0编辑  收藏  举报