假设有N个用户,其中有些人是朋友,有些则不是。A和B是朋友,B和C是朋友,这样ABC就是一个朋友圈,请计算给定的朋友关系的朋友圈数。
给定一个 N * N 的矩阵 M,表示用户之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个人互为朋友关系,否则为不知道。你必须输出所有用户中的已知的朋友圈总数。
第一行输入为表示用户数N第2到1+N行表示朋友之间关系,如果值为1表示有朋友关系
输出朋友圈数
3 1,1,0 1,1,0 0,0,1
2
第0个用户和第1个用户组成一个朋友圈,第2个用户组成一个朋友圈
3 1,1,0 1,1,1 0,1,1
1
第0,1,2个用户组成了一个朋友圈
如果M[i][j] = 1 那么 如果M[j][i] = 1,用户自己和自己肯定是朋友关系即M[i][i]=1用户数量不超过10000
import java.io.*; import java.util.*; public class Main{ public static void main(String[] args)throws Exception{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); int[][] arr = new int[n][n]; for(int i=0;i<n;++i){ String[] arg = br.readLine().split(","); for(int j=0;j<n;++j){ arr[i][j] = Integer.parseInt(arg[j]); } } int[] f = new int[n]; for(int i=0;i<n;++i){ f[i]=i; } for(int i=0;i<n;++i){ for(int j=0;j<n;++j){ if(arr[i][j] == 1){ union(f,i,j); } } } int ans =0; for(int i=0;i<n;++i){ if(f[i]==i){ ans++; } } System.out.println(ans); } public static int find(int[] f, int a){ if(f[a]==a){ return a; } return f[a] = find(f,f[a]); } public static void union(int[] f, int a,int b){ int fa = find(f,a); int fb = find(f,b); f[fa]=fb; } }
从每个未访问过的节点(用户)出发,进行 dfs
搜索。
dfs
的次数,就是朋友圈的数目。
import java.util.HashSet; import java.util.Scanner; import java.util.Set; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); String[][] relations = new String[n][n]; for (int i = 0; i < n; i++) { relations[i] = scanner.next().split(","); } scanner.close(); System.out.println(friendCircle(relations)); } private static int friendCircle(String[][] relations) { int n = relations.length; // graph[i] -> 用户 i 的所有朋友 Set[] graph = new HashSet[n]; for (int i = 0; i < n; i++) { graph[i] = new HashSet(); for (int j = 0; j < n; j++) { int relation = Integer.parseInt(relations[i][j]); if (relation == 1) { graph[i].add(j); } } } int ans = 0; boolean[] visited = new boolean[n]; for (int i = 0; i < n; i++) { if (!visited[i]) { ans++; dfs(graph, i, visited); } } return ans; } private static void dfs(Set[] graph, int cur, boolean[] visited) { visited[cur] = true; for (int next : graph[cur]) { if (!visited[next]) { dfs(graph, next, visited); } } } }
用一个set集合存储朋友圈列表。通过&与操作判断是否存在朋友关系,通过|或操作进行朋友圈融合,set集合剩下多少个元素代表有多少个朋友圈
public static void main(String[] args) { Scanner in = new Scanner(System.in); // 注意 hasNext 和 hasNextLine 的区别 int arrLen = Integer.parseInt(in.nextLine()); Set<Integer> binaryIntFC = new HashSet<>(); for (int i = 0; i < arrLen; i++) { String line = in.nextLine(); String[] split = line.split(","); StringBuilder sb = new StringBuilder(); for (int j = 0; j < split.length; j++) { sb.append(Integer.parseInt(split[j])); } binaryIntFC.add(Integer.parseInt(sb.toString(), 2)); } Set<Integer> friendCircles = new HashSet<>(); for (Integer binaryInt : binaryIntFC) { if (friendCircles.size() == 0) { friendCircles.add(binaryInt); continue; } // 判断当前set值与目标setlist是否有朋友关系,决定是否进行融合 boolean isFriend = false; for (Integer targetIntSet : friendCircles) { if ((targetIntSet & binaryInt) > 0) { // 有朋友关系,进行融合 int mergeInt = targetIntSet | binaryInt; friendCircles.remove(targetIntSet); friendCircles.add(mergeInt); isFriend = true; break; } } if (!isFriend) { // 没有朋友关系,直接加入到目标setlist中,成为一个新的朋友圈 friendCircles.add(binaryInt); } } System.out.println(friendCircles.size()); }
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String s = sc.nextLine(); int n = Integer.parseInt(s); UnionFindSet ufs = new UnionFindSet(n); int res = n; for (int i = 0; i < n; i++) { s = sc.nextLine(); String[] ss = s.split(","); for (int j = 0; j < i; j++) { int cur = Integer.parseInt(ss[j]); if (cur == 1) { res = ufs.union(i, j); } } } sc.close(); System.out.println(res); } static class UnionFindSet { int[] parent; int size; UnionFindSet(int n) { this.parent = new int[n]; for (int i = 0; i < n; i++) { parent[i] = i; } this.size = n; } int find(int n) { if (n == parent[n]) { return n; } int r = find(parent[n]); parent[n] = r; return r; } int union(int n1, int n2) { int r1 = find(n1), r2 = find(n2); if (r1 == r2) { return size; } else { if (r1 < r2) { parent[r2] = r1; } else { parent[r1] = r2; } return --size; } } } }
#include <iostream> #include <vector> using namespace std; // 并查集 class UnionFind { public: UnionFind(size_t n) :_v(n, -1) {} int FindIdx(int index) { while(_v[index] >= 0) { index = _v[index]; } return index; } bool Merge(int idx1, int idx2) { int root1 = FindIdx(idx1); int root2 = FindIdx(idx2); if(root1 == root2) return false; _v[root1] += _v[root2]; _v[root2] = root1; return true; } size_t Count() const { size_t count = 0; for(const auto& e : _v) { if(e < 0) count++; } return count; } vector<int> _v; }; int main() { int n; while(cin >> n) { vector<vector<int>> v(n, vector<int>(n, 0)); UnionFind uni(n); for(int i = 0; i < n; i++) { string str; cin >> str; for(int j = 0, k = 0; j < n; j++, k += 2) v[i][j] = str[k] - '0'; } for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { if(i == j) continue; if (v[i][j] == 1) uni.Merge(i, j); } } cout << uni.Count() << endl; } return 0; }
#include <iostream> bool temp[10001][10001]; int pre[10001]; //前驱 int unionsearch(int root) { int son, tmp; son = root; while (root != pre[root]) root = pre[root]; //寻找最终节点 while (son != root) { //路径压缩(递归) tmp = pre[son]; pre[son] = root; //root是最终节点 son = tmp; //向前寻找 } return root; } int main() { int a, b; int root1, root2; int total; char c; std::cin>>a; total = a; for(int i = 0; i < a; i++){ pre[i] = i; for(int j = 0; j < a; j++){ std::cin>>b; if(b == 1) temp[i][j] = true; if(j != a-1) std::cin>>c; } } for(int i = 0; i < a; i++){ for(int j = 0; j < i / 2 + 1; j++){ if(temp[i][j] == temp[j][i] && j!=i && temp[i][j]){ root1 = unionsearch(i); root2 = unionsearch(j); if(root1 != root2){ pre[root1] = root2; total--; } } } } std::cout<<total; return 0; }
import java.util.Scanner; /** * @author Frank KONG * @version 1.0 * @date 2021/2/24 10:47 */ public class Main { public static void main(String[] args) { int n; Scanner scanner = new Scanner(System.in); n = scanner.nextInt(); int[][] graph = new int[n][n]; for(int i = 0; i < n; i++){ String s = scanner.next(); String[] split = s.split(","); for(int j = 0; j < n; j++){ graph[i][j] = Integer.valueOf(split[j]); } } //0~n-1编号 int[] parent = new int[n]; for(int i = 0; i < n; i++){ parent[i] = i; } for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ if(graph[i][j] == 1){ //有关系,加入集合 int parentI = find(parent, i); int parentJ = find(parent, j); if(parentI != parentJ){ parent[parentI] = parentJ; } } } } //查看有几个集合 int res = 0; for(int i = 0; i < n; i++){ if(parent[i] == i) res++; } System.out.println(res); } public static int find(int[] parent, int index){ if(parent[index] != index){ index = parent[index]; } return index; } }