Shichikuji and Power Grid
题意还是很简单,每个点有点权,每个点之间也有边权
求最小生成森林,每个一颗最小生成树的权值等于边权+最小点权
思路
边权我们很好处理,有模板,但如何处理这个点权,便成了主要的问题
如果我们以边权的思路思考点权,那么点权就是某个点从到该点的边权
而我们可以假设0点为这个“某个点”,向每个点建边,那么最终求得的最小生成森林就会因为这个0点,连成一个最小生成树
最后建好边,套模板就可以了
CODE
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define x first
#define y second
typedef pair<int,int> pii;
typedef pair<ll,ll>pll;
const int maxn=2e3+10;
int cnt=0;
int head[maxn];
struct node{
int u,v;
ll w;
}e[maxn*maxn];
int c[maxn];
int n;
int k[maxn];
pii p[maxn];
int f[maxn];
vector<int> powerst;
vector<pii> edge;
ll val(int i,int j){
return (ll)(k[i]+k[j])*(abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y)) ;
}
int find(int x){
if(x!=f[x]) return f[x]=find(f[x]);
return x;
}
void init(){
cin>>n;
for(int i=1;i<=n;++i) cin>>p[i].x>>p[i].y;
for(int i=1;i<=n;++i) cin>>c[i],f[i]=i;
for(int i=1;i<=n;++i) cin>>k[i];
//0点
for(int i=1;i<=n;++i) {
e[++cnt].u=0;
e[cnt].v=i;
e[cnt].w=c[i];
}
//建边
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j){
e[++cnt].u=i;
e[cnt].v=j;
e[cnt].w=val(i,j);
}
}
bool cmp(node a,node b){
return a.w<b.w;
}
ll cost=0;
void krus(){
sort(e+1,e+1+cnt,cmp);
int tot=0;
for(int i=1;i<=cnt;++i){
int u=find(e[i].u);
int v=find(e[i].v);
if(u!=v){
if(e[i].u==0) powerst.push_back(e[i].v);
else {
edge.push_back(make_pair(e[i].u,e[i].v));
}
f[u]=v;
cost+=e[i].w;
if(++tot==n) break;
}
}
}
void print(){
cout<<cost<<endl;
cout<<powerst.size()<<endl;
if(!powerst.empty())
for(auto x:powerst){
cout<<x<<" ";
}
cout<<endl;
cout<<edge.size()<<endl;
if(!edge.empty())
for(auto t:edge){l
cout<<t.x<<" "<<t.y<<endl;
}
}
int main(){
cin.tie(0);cout.tie(0);
init();
krus();
print();
return 0;
}
小结
这个题关键的是转化点权的思路:点权化为边权
这个思路学会了,可能会在以后的题中可以应用
标签:ll,Power,int,点权,maxn,Grid,Shichikuji,边权 From: https://www.cnblogs.com/guiyou/p/18523035