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