Shichikuji and Power Grid

归游發表於2024-11-03

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

小結

這個題關鍵的是轉化點權的思路:點權化為邊權

這個思路學會了,可能會在以後的題中可以應用

相關文章