K

题目:K - Electrification Plan

题意:无向图,给n个点,n^2条边,每条边有个一权值,其中有k个点有发电站,给出这k个点的编号,选择最小权值的边,求使得剩下的点都能接收到电。

思路:将所有待选边加入优先队列(priority_queue 优先队列),用并查集判断待选边是否符合要求,符合(即不在同一并查集中)则合并。

代码:

/***********************************************/
ll n,k;
int a[109];
bool can[109];//此城市是否连通 
ll c[109][109];
int st[109];

struct node{
	int u,v;
	int w;//边的权 
};
bool operator < (const node& a,const node& b)
{//反过来,这样正好优先队列递增 
	return a.w>b.w;
}

int find(int a)
{
	while(a!=st[a]) a=st[a];
	return a;
}

void add(int a,int b)
{
	int fa=find(a);
	int fb=find(b);
	if(fa<fb) st[fb]=fa;
	else st[fa]=fb;
}

void Kruskal()
{
	ll ans=0;
	priority_queue<node>Q;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
		if(i!=j && find(i)!=find(j))
		{
			node t;
			t.u=i; t.v=j; t.w=c[i][j];
			Q.push(t);
		}
	while(!Q.empty())
	{
		node x=Q.top();
		Q.pop();
		if(find(x.u)!=find(x.v))
		{
			ans+=c[x.u][x.v];
			add(x.u,x.v);
		}
	}
	cout<<ans<<endl;
}

int main()
{
	std::ios::sync_with_stdio(false);
    std::cin.tie(0);
	cin>>n>>k; 
	for(int i=1;i<=n;i++) st[i]=i;
	for(int i=1;i<=k;i++){
		cin>>a[i];
		can[a[i]]=1;
		if(i>1){
			add(a[i],a[i-1]); 
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
			cin>>c[i][j];
	}
	Kruskal();
	return 0;
}

  

原文地址:https://www.cnblogs.com/liuyongliu/p/10346836.html