码迷,mamicode.com
首页 > 其他好文 > 详细

cf1242B

时间:2020-02-18 20:57:54      阅读:70      评论:0      收藏:0      [点我收藏+]

标签:out   题意   现在   算法   auto   生成树   生成   for   就是   

题意简述:给出一个n个点的完全图,边权要么是1要么是0,输入只给出权值的是1的那些边,求解最小生成树的权值

 

解答:边很多,我们考虑使用prim算法,prim算法的过程中维护了一个dis数组,这里我们可以发现数组的值单调递减,并且只有01两种取值

因此我们考虑用数据结构去加速他,具体来说就是维护两个集合一个集合存1,记为s1,一个存0记为s2

然后最重要的就是如何更新这个dis数组,也就是s1和s2的更新

显然我们只能去选择遍历权值为1的边,因此每加进去一个点,我们遍历他出发的所有的边,显然如果他出现在了s1中,那么这个数还应该出现在s1中,否则他就应该进去s2

这个操作我们可以用通过再加一个set搞定

int n,m;

vector<int> g[maxn];

bool vis[maxn];

int main(){
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		g[x].push_back(y);
		g[y].push_back(x);
	}
	vis[1]=1;
	set<int> zero,one;
	for(int i:g[1]){
		if(i!=1) {
			one.insert(i);
		}
	}
	for(int i=2;i<=n;i++)
		if(!one.count(i)) zero.insert(i);
	set<int> t;
	int ans=0;
	for(int cc=0;cc<n-1;cc++){
		int x;
		if(zero.size()) x=*zero.begin(),zero.erase(x);
		else x=*one.begin(),one.erase(x),ans++;
		t.clear();
		vis[x]=1;
		for(auto y:g[x]){
			if(!vis[y]) {
				if(one.count(y)) one.erase(y),t.insert(y);
			}
		}
		for(int y:one)
			zero.insert(y);
		one.clear();
		one=t;
	}
	cout<<ans<<endl;
}

  

 

cf1242B

标签:out   题意   现在   算法   auto   生成树   生成   for   就是   

原文地址:https://www.cnblogs.com/033000-/p/12327452.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!