zoukankan      html  css  js  c++  java
  • 2016奇虎360研发工程师内推笔试编程题:找镇长

    360员工桂最近申请了一个长假,一个人背着包出去自助游了。
      路上,他经过了一个小镇,发现小镇的人们都围在一棵树下争吵。桂上前询问情况,得知小镇的人们正缺一个镇长,他们希望能选一个知名又公正的镇长,即,大家希望能选出一个人,所有人都认识他,但同时他不认识镇上除自己以外的其他人(在此,我们默认每个人自己认识自己)。可是小镇里的人太多了,一下子大家谁也说服不了谁。
      “这简单啊。”桂表示。于是他一下子统计出来了镇上人们相互之间的认识关系,并且一下子找到了合适的镇长人选。
      现在你手上也拿到了这样一份认识关系的清单。其中上面给出的认识关系是单向的,即,A认识B与B认识A是相互独立的,只给出A认识B就不能认为B认识A,例如,我认识你,你不一定认识我。而且,这里的认识关系也不具有传递性,即,A认识B,B认识C,但这不代表A认识C。同时,为了方便处理,这份清单中,镇上的N个人依次编号为1到N。你能否像桂一样快速找到合适的镇长人选呢? 
    输入描述:
    首先一个正整数T(T≤20),表示数据组数。
    之后每组数据的第一行有2个整数n  和m  (1≤n≤105 ,0≤m≤3×105 ),依次表示镇上的人数和相互之间的认识关系数。
    之后m行,第 i 行每行两个数Ai和Bi   (1≤Ai ,Bi ≤n  ),表示Ai认识Bi。(保证没有重复的认识关系,但可能存在自己认识自己的认识关系)
    保证所有数据中80%的数据满足n≤1000,m≤10000
    输出描述:
    一共2T 行,每组数据对应2行。
    第一行,一个整数,表示你所找出来的合适的镇长人选人数num i   。
    第二行,num i 个整数,每两个数中间用空格隔开,表示你所选的合适的镇长的编号。
    特别的,如果并没有找到合适的镇长,第一行输出一个数0,第二行留空即可(参见样例)。
    输入例子:
    3
    2 0
    3 2
    1 2
    3 2
    4 5
    1 1
    2 1
    3 1
    4 1
    3 3
    输出例子:
    0
    
    1
    2
    1
    1

    解题

    题意:找到其他人都认识他,而他都不认识其他人的那个他
    定义人数的矩阵,表示关系
    A[i][j] 表示 i 人 与 j人的关系,为 1 的时候表示认识 ,0 不认识,i==j 表示自己认识自己
    答案满足:
    该 i 行只有 A[i][i] 为1,其他都为 0
    该 i 列元素都为 1

     1 package a_360;
     2 
     3 import java.util.ArrayList;
     4 import java.util.Scanner;
     5 
     6 public class Main{
     7 
     8     /**
     9      * 题目:
    10      * 找出别人都认识他,而他其他人都不认识的人
    11      * 输入:
    12      * T T个这样的测试样例
    13      * n m n个人 m个关系数
    14      * 下面m行就是关系数
    15      * 输出:
    16      * 第一行:这样的人有几个
    17      * 满足条件人的编号
    18      * 
    19      * 若不存在,输出 0 空格
    20      */
    21     public static void main(String[] args) {
    22         // TODO Auto-generated method stub
    23         Scanner scn = new Scanner(System.in);
    24         int T = scn.nextInt(); // 测试数据组数
    25         for (int i = 0; i < T; i++) {
    26             int n = scn.nextInt(); // 人数
    27             int m = scn.nextInt(); // 关系数
    28             if(m==0 || n==1){
    29                 System.out.println(0);
    30                 System.out.println();
    31                 continue;
    32             }
    33             int[][] A = new int[n][n];
    34             
    35             for(int k =0;k<m;k++){
    36                 int m1 = scn.nextInt();
    37                 int m2 = scn.nextInt();
    38                 A[m1-1][m2-1] = 1;
    39             }
    40             // 对角值为 1 
    41             for(int k =0;k<n;k++){
    42                 A[k][k] = 1;
    43             }
    44             relation_0(A);
    45         }
    46     }
    47 
    48     public static void relation_0(int[][] A){
    49         // 关系已经存在二维数组中,找出二维数组中行只有对角位置是1 ,对角位置所在的列都是 1
    50         int count = 0;
    51         ArrayList<Integer> res = new ArrayList<Integer>();
    52         for(int i = 0;i<A.length;i++){
    53             boolean row1 = true;
    54             boolean col1 = true;
    55             // 判断第 i列是否都是1 都是1 说明别人都认识他
    56             for(int row = 0;row<A.length;row++){
    57                 if(A[row][i] == 0){
    58                     col1 = false;
    59                     break;
    60                 }
    61             }
    62             if(col1){
    63                 // 判断第 i 行是否只有对角是 1 意思 别人都不认识他,对角是自己认识自己
    64                 for(int col = 0;col<A.length;col++){
    65                     // == 1 说明有人认识他 
    66                     if(col!=i && A[i][col]==1){
    67                         row1 = false;
    68                         break;
    69                     }
    70                 }
    71             }
    72             if(row1 && col1){
    73                 count++;
    74                 res.add(i+1);
    75             }
    76         }
    77         System.out.println(count);
    78         for(int i = 0;i<res.size();i++){
    79             System.out.println(res.get(i));
    80         }
    81     }
    82 
    83 }

    牛客测试内存溢出,给的样例本地测试通过

    上面在判断列全是 1 的时候可以对改行的元素求和,和等于人数n的时候符合条件

    在判断行只有1的并且是自己认识自己的时候,可以变相的认为和是 0 

    但是上面还是不能改变定义矩阵的情况

    上面可以看到,我们用到的只是矩阵的行的和,和矩阵列的和

    定义两个向量来存放行的和和列的和。

    定义两个数组:A B

    A[i] 表示 i 认识的人数

    B[i] 表示 认识 i 的人数 

    上面去除自己认识自己的情况

    当A[i] == 0 B[i] = n-1 的时候 说明这个人不认识别人,却被 n -1个人认识就是答案

    题目中说可以有多个,其实最多只有一个,因为这个人要被其余 n -1 个人认识,就不存在两个人的情况了

    在牛客不知道为什么下面程序提示“运行错误:请检查是否存在数组越界非法访问,野指针乱访问,空指针乱访问等情况”

     1 import java.util.Scanner;
     2 
     3 public class Main {
     4 
     5     /**
     6      * 题目:
     7      * 找出别人都认识他,而他其他人都不认识的人
     8      * 输入:
     9      * T T个这样的测试样例
    10      * n m n个人 m个关系数
    11      * 下面m行就是关系数
    12      * 输出:
    13      * 第一行:这样的人有几个
    14      * 满足条件人的编号
    15      * 
    16      * 若不存在,输出 0 空格
    17      */
    18     public static void main(String[] args) {
    19         // TODO Auto-generated method stub
    20         Scanner scn = new Scanner(System.in);
    21         int T = scn.nextInt(); // 测试数据组数
    22         while((T--)>0) {
    23             int n = scn.nextInt(); // 人数
    24             int m = scn.nextInt(); // 关系数
    25             if(n == 1){
    26                 System.out.print(1+"
    "+1);
    27                 continue;
    28             }
    29             if(m<n-1){
    30                 System.out.print(0+"
    "+0);
    31                 continue;
    32             }
    33 
    34             // 认识人的数量
    35             int[] A = new int[n+1];
    36             // 被认识的数量
    37             int[] B = new int[n+1];
    38             // m1 认识 m2 
    39             for(int k =0;k<m;k++){
    40                 int m1 = scn.nextInt();
    41                 int m2 = scn.nextInt();
    42                 
    43                 if(m1!=m2){
    44                     // m1 认识的人数 去除自己的情况
    45                     A[m1]++;
    46                     //m2 被多少人认识,去除自己的情况
    47                     B[m2]++;
    48                 }
    49             }
    50             // 自己认识自己的情况可以不用考虑,A[i] = 0 表示 i 不认识除自己以外的其他人, B[i] = n-1 表示i 其他人都认识
    51             int id = -1;
    52             for(int kk = 1;kk<=n;kk++){
    53                 if(A[kk]==0 && B[kk]==n-1){
    54                     id = kk;
    55                     break;
    56                 }
    57             }
    58             if(id == -1){
    59                 System.out.print("0
    
    ");
    60             }else{
    61                 System.out.print(1+"
    "+id+"
    ");
    62             }
    63             
    64         }
    65     }
    66 
    67 
    68 }


  • 相关阅读:
    Linux 共享库
    使用Visual Studio(VS)开发Qt程序代码提示功能的实现(转)
    ZOJ 3469 Food Delivery(区间DP)
    POJ 2955 Brackets (区间DP)
    HDU 3555 Bomb(数位DP)
    HDU 2089 不要62(数位DP)
    UESTC 1307 windy数(数位DP)
    HDU 4352 XHXJ's LIS(数位DP)
    POJ 3252 Round Numbers(数位DP)
    HDU 2476 String painter (区间DP)
  • 原文地址:https://www.cnblogs.com/theskulls/p/5276848.html
Copyright © 2011-2022 走看看