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;
}