D. 0-1 MST map用例 ::iterator

D. 0-1 MST map用例 ::iterator

inerator

stl map 的 map<int,int>::iterator it 迭代器
用于遍历map中的每一个函数

D. 0-1 MST

CodeForces 1243D -> Click here

题意

一个 n 个节点的完整图,m条边的边长为 1 ,其余的边长度为 0 问 minimum spanning tree 所要花费的最小代价(边长和最小)

思路

考虑 minimum spanning tree 花费的最小代价为 尽量全部用零边连接所有的点 剩下没有相连的点之间加一条 1边 使其形成 spanning tree
就从每个点出发 DFS 最大可用零边相连的点
从1 到 n DFS 一遍 找到每个点可用 0边 连到的最大连通块 最后统计连通块个数

code

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=(a);i<=(b);i++)
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
using namespace std;
typedef long long ll;
int n,m;
map<int,int> mpp;
map<int,int> mp;
vector<int> G[100005];
void dfs(int x){
	mpp[x]=1;
	map<int,int> fp;
	for(int i=0;i<G[x].size();i++){//循环此点的 壹边 在mp中移除
		mp.erase(G[x][i]);// 此点在mp中移除
		fp[G[x][i]]=G[x][i];// 在fp中加入
	}
	swap(mp,fp);//map 的swap :交换mp和fp两个容器
    // fp存于x点有零边的点
	for(map<int,int>::iterator i=fp.begin();i!=fp.end();i++){// 遍历map容器
        // map<int,int>::iterator i 用于遍历map中的
		int to=i->first;
		if(mpp[to]) continue;
		dfs(to);
	}
}
void solve(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) mp[i]=i;//mp 存储未被遍历过的点
	for(int i=1;i<=m;i++){//存边
		int a,b;cin>>a>>b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		if(mpp[i]==1) continue;//如果已经被遍历过了 则跳过
		ans++;//没被遍历过 说明不与之前遍历过的点处在一个零边联通块中 ans++
		dfs(i);//从这个点开始深度搜索与其有零边相连的点
	}
	cout<<ans-1<<endl;
}
int main(){
	solve();
	return 0;
}
posted @ 2021-08-02 22:31  莳曳  阅读(60)  评论(0)    收藏  举报