小伍开网吧

题目描述

小伍开了一个网吧,机房里有若干台电脑,其中有一些电脑已经相互连接。如果A和B通过网线相连,并且B与C也通过网线相连,那么即便A和C之间没有直接的网线相连,也可以认为A和C是相连的(即A,B,C为一组电脑)。由于机房里的布线比较乱,并不是所有电脑都相互连通,

输入

多组数据。每组数据第一行为整数N,M。N是电脑数量,M是机房已布置好的网线数量。接下来M行,每行为整数A,B。表明A,B之间通过一条网线直接相连。这里可以认为网线是不分方向的,即A->B等价于B->A。
(0 < N <= 200,0 <= M <= 10000,0 < A,B <= N 。) N=0和M=0为输入结束,不需要处理。 

输出

请你帮小伍统计一下共有多少组电脑 ,先输出M组,下面M行按序号大小输出每组电脑,空格分开,行末也有空格。

样例输入

<span style="color:#333333"><span style="color:#333333">4 2
1 2
2 3
0 0
</span></span>

样例输出

<span style="color:#333333"><span style="color:#333333">2
1 2 3 
4 </span></span>

import java.util.*;

public class Main {
    static Scanner cin = new Scanner(System.in);
    static int n,m;
    public static  void main(String[] args) {
        while(cin.hasNext()) {
            n = cin.nextInt();
            m = cin.nextInt();
            if(n==0&&m==0) break;
            Graph G = new Graph();
            CC cc = new CC(G);
            System.out.println(cc.getCount());
            List<Integer>[] list = new LinkedList[cc.getCount()];
            for (int i = 0; i < cc.getCount(); i++) {
                list[i] = new LinkedList<>();
            }
            for (int i = 1; i <= n; i++) {
                list[cc.id(i)].add(i);
            }
            for (int i = 0; i < cc.getCount(); i++) {
                for(Integer v:list[i]){
                    System.out.print(v+" ");
                }
                System.out.println();
            }
        }

        cin.close();
    }
    private static class Graph {
        static List []adj;
        public Graph() {
            adj=new LinkedList[n+1];
            for(int i=1;i<=n;i++){
                adj[i]=new LinkedList<>();
            }
            for(int i=0;i<m;i++){
                int v=cin.nextInt();
                int w=cin.nextInt();
                addEdge(v,w);
            }
        }
        private void addEdge(int v, int w) {
            adj[v].add(w);
            adj[w].add(v);
        }
        public Iterable<Integer> adj(int v){
            return adj[v];
        }

    }
    private static class CC {
        private boolean []marked;
        private int []id;
        private int count;
        public CC(Graph G) {
            marked=new boolean[n+1];
            id=new int[n+1];
            for(int i=1;i<n+1;i++){
                if(!marked[i]){
                    dfs(G,i);
                    count++;
                }
            }
        }
        private void dfs(Graph G, int i) {
            marked[i]=true;
            id[i]=count;
            for(int w:G.adj(i)){
                if(!marked[w]){
                    dfs(G,w);
                }
            }
        }
        public int getCount() {
            return count;
        }
        public int id(int v){
            return id[v];
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值