#include<bits/stdc++.h> using namespace std; /*并查集,开辟一个大数组*/ const int MAXN=1000001; int father[MAXN]; int appear[MAXN];//1表示appear[i]出现过 void Initial() { for(int i=0;i<MAXN;i++) { father[i]=-1; appear[i]=0; } } int Find(int x) { while(father[x]!=-1) x=father[x]; return x; } void Union(int x,int y)//根节点的合并集合 { x=Find(x); y=Find(y); if(x!=y) father[y]=x; return ; } int main() { int x,y; Initial(); while(cin>>x>>y) { Union(x,y); appear[x]=1; appear[y]=1; //x和y出现过则置为1 } int component=0; for(int i=0;i<MAXN;i++) if(appear[i]==1&&father[i]==-1) component++; //因为之前合并过集合所以father[i]==-1说明有一个连通分量,且要出现过 cout<<component<<endl; return 0; }
#include<iostream> #include<cstdio> #include<queue> #include<cmath> #include<algorithm> #include<cstring> #include <sstream> #include<map> using namespace std; int fa[1000005]; bool vis[1000005]; int get(int root){ if(fa[root]==root) return root; else return fa[root]=get(fa[root]); } int main(){ int a,b; memset(vis,0,sizeof(vis)); for(int i=0;i<=1000000;i++) fa[i]=i; while(cin>>a>>b){ vis[a]=true; vis[b]=true; a=get(a); b=get(b); fa[a]=b; } int ans=0; for(int i=0;i<=1000000;i++){ if(vis[i]==true){ if(fa[i]==i) ans++; } } cout<<ans<<endl; }
/* *根据输入的数据生成并查集 , 然后查询根节点的个数 */ #include<bits/stdc++.h> using namespace std; const int maxn = 1e6; int father[maxn+5]; void Initial() //初始化父节点数组 { for(int i = 0;i < maxn; i++) father[i] = i; } int getFather(int x) //找到根节点 { int a = x; while(x != father[x]) x = father[x]; //路径压缩 while(a != father[a]) { int z = a; a = father[a]; father[z] = x; } return x; } void Union(int a, int b) //合并 { int fa = getFather(a); int fb = getFather(b); if(fa != fb) father[fa] = fb; } int main() { ios::sync_with_stdio(false); int a, b; set<int> s; Initial(); while(cin >> a >> b) { Union(a, b); s.insert(a); s.insert(b); } int ans = 0; for(int i : s) ans += father[i] == i? 1 : 0; cout << ans << "\n"; return 0; }
#include <stdio.h> #include <iostream> #include <algorithm> #include <vector> #include <map> using namespace std; map <int,int> table; int find(int x){ if(table.find(x)==table.end()||table[x]==x){ return x; } else{ table[x]=find(table[x]); //路径压缩 } return table[x] } int main() { int a,b; while(cin>>a>>b){ //读入数据,构建并查集 if(a==0){ break; } a=find(a); b=find(b); table[a]=b; table[b]=b; } map<int,int>::iterator iter; int count=0; for(iter=table.begin();iter!=table.end();iter++){ if(iter->second==iter->first){ count++; } } cout<<count<<'\n'; }
#include<bits/stdc++.h> using namespace std; void dfs(bool vis[], map<int, set<int> > &ms, int i) { vis[i] = 1; for(auto mi=ms[i].begin(); mi!=ms[i].end(); mi++){ if(!vis[*mi]){ dfs(vis, ms, *mi); } } } int main() { map<int, int> m; map<int, set<int> > ms; int a, b, cnt = 0; while(cin>>a>>b){ if(m.find(a) == m.end()){ m[a] = cnt++; set<int> s; ms[m[a]] = s; } if(m.find(b) == m.end()){ m[b] = cnt++; set<int> s; ms[m[b]] = s; } if(a != b){ ms[m[a]].insert(m[b]); ms[m[b]].insert(m[a]); } } bool vis[cnt]; memset(vis, 0, sizeof(vis)); int res = 0; for(int i=0; i<cnt; i++){ if(!vis[i]){ res++; dfs(vis, ms, i); } } cout<<res; return 0; }
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> #include <stack> #include <cmath> #include <map> #include <vector> #include <set> using namespace std; map<int, bool> visit; map<int, vector<int> > mp; void dfs(int x) { visit[x] = 1; for(int i = 0;i<mp[x].size();i++) { if(!visit[mp[x][i]]) dfs(mp[x][i]); } } int main() { visit.clear(); mp.clear(); set<int> st; st.clear(); int x,y; while(cin >> x >> y) { st.insert(x); st.insert(y); mp[x].push_back(y); mp[y].push_back(x); } int ans = 0 ; for(set<int>::iterator it = st.begin() ; it != st.end(); ++it) { if(visit[*it] == 0) { ans++; dfs(*it); } } cout << ans << endl; }
/* DFS 1.只有有边的点参与计算联通分支数,所以将vis默认为true,当有输入边时,设顶点为false,就可以只考虑有边的顶点的DFS。 2.顶点最大数量MAXN至少设置1000010。100010都不行。 */ #include <cstdio> #include <vector> #include <iostream> using namespace std; const int MAXN=1000010; vector<int> Adj[MAXN]; bool vis[MAXN]; void DFS(int u) { vis[u]=true; for(int i=0;i<Adj[u].size();i++) { int v=Adj[u][i]; if(vis[v]==false) DFS(v); } } int main() { fill(vis,vis+MAXN,true); int v1,v2; while(scanf("%d%d",&v1,&v2)!=EOF) { Adj[v1].push_back(v2); Adj[v2].push_back(v1); //只有有边的点参与计算联通分支数 vis[v1]=vis[v2]=false; } int count=0; for(int i=0;i<MAXN;i++) { if(vis[i]==false) { DFS(i); count++; } } printf("%d\n",count); return 0; }
#include <iostream> #include <set> using namespace std; #define N 1000000 int Tree[N]; int findRoot(int x){ if(Tree[x]==-1) return x; int temp=findRoot(Tree[x]); Tree[x]=temp; return temp; } int main(){ int a,b; set<int>s; for(int i=0;i<N;i++) Tree[i]=-1; while(cin>>a>>b){ s.insert(a); s.insert(b); a=findRoot(a); b=findRoot(b); if(a!=b) Tree[a]=b; } int ans=0; set<int>::iterator it; for(it=s.begin ();it!=s.end ();it++) if(Tree[*it]==-1) ans++; cout<<ans<<endl; return 0; }
//const int MAX=1000010;
#include<iostream> (720)#include<cstdio> using namespace std; const int MAX=1000010; int father[MAX]; int height[MAX]; bool visit[MAX]; void Init(){ for(int i=1;i<MAX;i++){ father[i]=i; height[i]=0; visit[MAX]=false; } } int Find(int x){ if(x!=father[x]){ father[x]=Find(father[x]); } return father[x]; } void Union(int x,int y){ x=Find(x); y=Find(y); if(x!=y){ if(height[x]<height[y]){ father[x]=y; }else if(height[x]>height[y]){ father[y]=x; }else{ father[y]=x; height[x]++; } } } int main(){ Init(); int MaxNum=0; int x,y; while(scanf("%d%d",&x,&y)!=EOF){ Union(x,y); visit[x]=true; visit[y]=true; MaxNum=MaxNum>x?MaxNum:x;//为了缩小下面的遍历范围 保留这一个文件中最大编号的节点 MaxNum=MaxNum>y?MaxNum:y; } int component=0; for(int i=1;i<=MaxNum;i++){ if(!visit[i]) continue; if(father[i]==i) component++; } printf("%d\n",component); return 0; }
#include<iostream> #include<vector> #include<map> #include<algorithm> using namespace std; map<int,int> father; //通过散列表map实现的father数组 map<int,int> height; //记录每个节点的高度 int find(int x){ if(father.find(x)!=father.end()){ if(father[x]!=x) father[x]=find(father[x]); //路径压缩(最后自己通过例子模拟下过程) } else{//如果还没有出现的新节点。把father设成他自己(表示根节点),height设成0 father[x]=x; height[x]=0; } return father[x]; } void Union(int a,int b){//合并函数 a=find(a); b=find(b); if(a!=b){ if(height[a]>height[b]) father[b]=a; else if(height[b]>height[a]) father[a]=b; else{ father[a]=b; height[a]++; } } } int main() { int i,j; while(cin>>i>>j){ //if(i==0)break; Union(i,j); } int sum=0; for(auto it=father.begin();it!=father.end();it++){ if(it->first==it->second)sum++; //只要有一个父亲是本身的就说明是根节点 } cout<<sum<<endl; return 0; }
#include <iostream> #include<map> using namespace std; map<int, int>mp; //map用来映射每个顶点对应的父节点是什么 int find(int x) { //用于找到父节点以及路径压缩 if (x != mp[x]) mp[x] = find(mp[x]); return mp[x]; } void union_two(int A, int B) { int c1 = find(A); int c2 = find(B); if (c1 != c2) mp[c2] = c1; //若相连接的两个结点根结点不同,则合并两个根结点 } int main() { //这是简单的并查集的运用,因为序号不是连续的则用map映射来实现,表示存储对应的连接关系 int a, b; while (cin >> a >> b) { if (mp.find(a) ==mp.end()) { //若已有映射中无对应的结点则存入顶点信息,并将其根节点设为自己 mp[a] = a; } if (mp.find(b) ==mp.end()) { mp[b] = b; } union_two(a, b); } int cnt = 0; //处理完所有的信息之后,再判断联通分支数为多少,其为该顶点的编号与对应父节点的编号相同的顶点的数量 for (auto it : mp) { if (it.first==it.second) cnt++; } cout << cnt << endl; return 0; }
#include<bits/stdc++.h> using namespace std; vector<int> adj[500000]; map<int,int> mp; void dfs(int u){ mp[u]=1; for(int i=0;i<adj[u].size();i++){ if(mp[adj[u][i]]==0){ dfs(adj[u][i]); } } } void dfsTravel(int& count){ for(map<int,int>::iterator it=mp.begin();it!=mp.end();it++){ if(it->second==0){ dfs(it->first); count++; } } } int main(){ int i,j; //memset(visited,0,sizeof(visited)); while(cin>>i>>j){ adj[i].push_back(j); adj[j].push_back(i); mp[i]=mp[j]=0; } int count=0; dfsTravel(count); cout<<count<<endl; return 0; }
DFS 染色,一次染一个联通集
#include <functional> #include <iostream> #include <unordered_map> #include <unordered_set> #include <vector> using namespace std; int main() { unordered_map<int, vector<int>> g; unordered_set<int> st; int a, b; while (cin >> a >> b) { st.insert(a); st.insert(b); if (a == b) continue; g[a].push_back(b); g[b].push_back(a); } unordered_map<int, bool> vis; vector<int> nodes(st.begin(), st.end()); for (auto& [k, v]: g) vis[k] = false; function<void(int, int)> dfs = [&](int cur, int pre) { if (vis[cur] == true) return; vis[cur] = true; for (auto nxt: g[cur]) { if (nxt != pre && !vis[nxt]) { dfs(nxt, cur); } } }; int ans = 0; for (int & node : nodes) { if (!vis[node]) { dfs(node, -1); ans++; } } cout << ans; }
#include <iostream> #include <vector> #include <cstdio> #include <cmath> #include <set> using namespace std; int top[2000001], setRank[2000001]; //数据范围一定要够大,有点毒瘤了 set<int> nodeSet; void init(int x) { for(int i = 1; i <= x; i++) { top[i] = i; setRank[i] = 0; } } //非递归写法,常数有所优化 int find(int x) { while(top[x] != x) { int t = x; x = top[x]; top[t] = top[x]; } return x; } void set_union(int x, int y) { int fx = find(x), fy = find(y); if(fx != fy) { if(setRank[fx] > setRank[fy]) top[fy] = fx; else if(setRank[fx] < setRank[fy]) top[fx] = fy; else top[fy] = fx, setRank[fx] ++; } } int main() { int m, n; int max_num = -1; init(2000000); while(cin >> m >> n) { nodeSet.insert(m); nodeSet.insert(n); set_union(m, n); } int cnt = 0; for(auto i : nodeSet) { if(find(i) == i) cnt++; } cout << cnt << endl; return 0; }
use std::io::{self, *}; fn main() { println!("26202"); }
#include <bits/stdc++.h> using namespace std; const int N = 1000010; vector<int> father(N, 0); int find(int u){ return father[u] == -1 ? u : father[u] = find(father[u]); } void join(int u, int v){ u = find(u); v = find(v); if( u == v) return; else father[v] = u; } int main() { int u, v; while(cin>>u>>v){ if(father[u] == 0) father[u] = -1; if(father[v] == 0) father[v] = -1; join(u, v); } int count = 0; for(int i = 0; i < N; i++){ if(father[i] == -1) count++; } cout<<count<<endl; }
#include <cstdint> #include <iostream> #include<vector> #include<map> using namespace std; map<int,int>node; struct pairnode{ int first; int second; pairnode(int _first,int _second){ first=_first; second=_second; } }; void Init(int visit[],int n){ for(int i=0;i<n;i++){ visit[i]=i; } } int findfather(int visit[],int n){ if(visit[n]==n){ return n; } else return findfather(visit,visit[n]); } int main() { vector<pairnode> v; int a, b; int i=0; int u, w; while (cin >> a >> b) { if (node.count(a) == 0) { node.insert({a,i++}); } if (node.count(b) == 0) { node.insert({b,i++}); } pairnode p(a, b); v.push_back(p); } int setnode = node.size(); int visit[setnode]; Init(visit,setnode); for (i = 0; i < v.size(); i++) { u = v[i].first; w = v[i].second; int uroot = findfather(visit,node[u]); int wroot = findfather(visit,node[w]); if (uroot != wroot) { setnode--; visit[wroot]=uroot; } } cout << setnode << endl; return 0; }
#include <iostream> #include <cstdio> #include <map> using namespace std; int parent[1000000]; map<int, int> ::iterator it; void innital(int n, map<int, int>& nodes) {//nodes在主函数,注意传参 it = nodes.find(n); if (it == nodes.end()) { nodes[n] = 1; parent[n] = -1; } } int findroot(int x) { while (parent[x] != -1) x = parent[x]; return x; } int unionset(int n1, int n2, int parent[1000000]) { int n1_root, n2_root; n1_root = findroot(n1); n2_root = findroot(n2); if (n1_root == n2_root) return 0; //同集合不用合并 else { parent[n1_root] = n2_root; return 1; } } int main() {//统计入度为0的节点的数量。如果入度为0的节点数量大于1,则不满足树的定义。检查是否有环路存在。 int n1, n2; int k = 0; int flag = 1; map<int, int> nodes; map<int, int> degree; while (cin >> n1 >> n2) { innital(n1, nodes); innital(n2, nodes); unionset(n1, n2, parent); //集合合并,合并失败有环 } int j = 0; for (it = nodes.begin(); it != nodes.end(); it++) { int n=it->first; if (findroot(n)==n) j++; } cout<<j<<endl; return 0; }
import sys nodes = set() edges = [] for line in sys.stdin: start, end = list(map(int, line.strip().split())) nodes.add(start) nodes.add(end) edges.append([start, end]) edges.append([end, start]) nodes = list(nodes) adjusts = {} isvisited = {} for node in nodes: adjusts[node] = [] isvisited[node] = False for start, end in edges: if start == end: pass else: adjusts[start].append(end) count = 0 for node in nodes: if not isvisited[node]: count += 1 queue = [node] while len(queue) > 0: cur = queue[0] queue.pop(0) for next_node in adjusts[cur]: if not isvisited[next_node]: queue.append(next_node) isvisited[next_node] = True print(count)