8.29顺丰科技

5 3 4
1 1
3 1
3 2
5 3

 

5 3 0

 题意大概就是给这样一个左右的连通图,黑色的线是题目给的,然后问怎么加最少的线,使得图中左边的节点可以相互连接。

方法1.用图的方法,求连通域,这里1,3是一个连通域(可以相互走到),2,4,5分别是一个连通域

最后结果是连通域个数减1,特殊情况,图中线为0的时候,结果为左边节点个数

public class Main { 
    public static void main(String[] args) {         
          Scanner sc=new Scanner(System.in);
          Main s=new Main();
          int n=sc.nextInt();
          int m=sc.nextInt();
          int k=sc.nextInt();
          if(k==0) {
              System.out.println(n);
              return;
          }
          HashMap<Integer, ArrayList<Integer>> nTm=new HashMap<>();
          HashMap<Integer, ArrayList<Integer>> mTn=new HashMap<>();
          for(int i=0;i<k;i++) {
              int l=sc.nextInt();
              int r=sc.nextInt();
              if(nTm.containsKey(l)) {
                  nTm.get(l).add(r);
              }
              else
              {
                  nTm.put(l, new ArrayList<>());
                  nTm.get(l).add(r);
              }
              
              if(mTn.containsKey(r)) {
                  mTn.get(r).add(l);
              }
              else
              {
                  mTn.put(r, new ArrayList<>());
                  mTn.get(r).add(l);
              }
          }   
          int[] vis=new int[n+1];
          int SumN=0;
          for(int i=1;i<=n;i++) {
              if(vis[i]==0) {
                  dfs(SumN,i,vis,nTm,mTn);
                  SumN++;
              }
          }
          System.out.println(SumN-1);          
     } 
     public static void dfs(int SumN,int u,int[] vis,HashMap<Integer, ArrayList<Integer>> nTm,HashMap<Integer, ArrayList<Integer>> mTn){
        vis[u] = 1;
        if(!nTm.containsKey(u)) return;
        int sumM = nTm.get(u).size();
        for(int i = 0;i<sumM;i++){
            int z = nTm.get(u).get(i);
            int len = mTn.get(z).size();
            for(int j = 0;j<len;j++){
                int v = mTn.get(z).get(j);
                if(vis[v] == 0){
                    dfs(SumN,v,vis,nTm,mTn);
                }
            }
        }
     }
}

方法2,并查集

右边的节点都是作为父节点

public class Main { 
    static UnionNode[] nodes;
    static Map<Integer, List<Integer>> map = new HashMap<>();//右边节点为key维持这样一个map
    static class UnionNode{//针对左边的节点 
        int val;
        int father=-1;     
        public UnionNode(int val, int father) {
            this.val = val;
            this.father = father;
        }
        int getFather() {
            return nodes[val].father;
        }
    }    
    static void set(int target,int nowFather) {            
        int temp = nodes[target].getFather();//获取原先的父亲
        if(temp!=-1) {
            List<Integer> list=map.get(nowFather);
            for(Integer i:list) {
                nodes[i].father=temp;
            }
        }
        else
        {
            nodes[target].father=nowFather;
        }
    }
    public static void main(String[] args) {         
          Scanner sc=new Scanner(System.in);
          Main s=new Main();
          int n=sc.nextInt();
          int m=sc.nextInt();
          int k=sc.nextInt();
          if(k==0) {
              System.out.println(n);
              return;
          }
          nodes=new UnionNode[n+1];
          for(int i=1;i<=n;i++) nodes[i]=new UnionNode(i,-1);
          for(int i=0;i<k;i++) {
              int l=sc.nextInt();
              int r=sc.nextInt();
              List<Integer> list = map.getOrDefault(r, new ArrayList<>());
              list.add(l);
              map.put(r, list);
              set(l,r);             
          } 
          HashSet<Integer> set=new HashSet<>();
          int num=0;
          for(int i=1;i<nodes.length;i++) {
              if(nodes[i].father==-1) {
                  num++;
              }
              else
              {
                  set.add(nodes[i].father);
              }
          }
          System.out.println(set.size()-1+num);
     } 
}

 

posted @ 2019-08-30 10:47  LeeJuly  阅读(126)  评论(0)    收藏  举报