标签: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; }
标签:out 题意 现在 算法 auto 生成树 生成 for 就是
原文地址:https://www.cnblogs.com/033000-/p/12327452.html