最后接电话的人 - 算法

一、问题描述
这里写图片描述

约束:如图所示是一个联系人网络,圆圈上面的标号代表人的标号,箭头方向表示前节点可以给后节点打电话,起点为2(例如:2可以给7和15打电话。注意在打电话的时候2是需要同时给7和15打电话。然后,7给1打电话,同时,1给4打电话。)
问题:求打电话步数最多并且人物编号最大的人的编号?

*输入:*2 7 11 6 6 2 2 15 15 4 4 2 4 10 7 1 1 7 1 8 1 17 3 22
(from,to;from,to;from,to…)
(解释:2->7;11->6;6->2…)
上图访问路径:
2 -> 7 ->1 -> 17(4步)
2 -> 7 -> 1 -> 8 (4步)
2 -> 15 -> 4 -> 10 (4步)
答案:17

二、特殊情况
1.构成简单循环:
上图中 7 可以给 1 打电话,1 也可以给 7 打电话;2 ->5 -> 4 -> 2 构成一个循环,循环的情况应该去除!应该标记,访问过的人就不再访问,

2.构成复杂循环:
输入:2 7 11 6 6 2 2 15 15 4 4 2 4 10 7 1 1 7 1 8 1 17 3 22 7 17
分析:
上图访问路径:
2 -> 7 ->1 -> 17(4步)
2 -> 7 -> 1 -> 8 (4步)
2 -> 7 -> 17(3步),17号元素在第一条路径中是第四步被访问,但是在当前这条路径中是第三步,所以根据题意,最后的结果应该是10;
2 -> 15 -> 4 -> 10 (4步)
答案:10

如图:
这里写图片描述

三、代码(dfs)
将输入数据转化为 二维表,打电话的人为 第一列,接电话的人为第二列

package com.daxiong.day11;

import java.io.*;
import java.util.*;

public class Graph {

    private static int[][] data = new int[100][2];
    private static int size = 1;
    private static int[] visit = new int[100];
    private static int steps = 1;
    private static int maxPerson = 0;

    private static int answer = 0;
    private static int maxSteps = 0;

    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(new File("src/resource/case2.txt"));
        while (sc.hasNextInt()) {
            data[size][0] = sc.nextInt();
            maxPerson = data[size][0];
            for(int i = 0;i < size;i++){  // 寻找最大编号
                if(maxPerson < data[i][0]){
                    maxPerson = data[i][0];
                }
            }
            data[size][1] = sc.nextInt();
            for(int i = 0;i < size;i++){  // 寻找最大编号
                if(maxPerson < data[i][1]){
                    maxPerson = data[i][1];
                }
            }
            size++;
        }
        dfs(data[1][0]);
        //System.out.println("maxSteps:" + maxSteps);
        for (int i = maxPerson; i >= 1; i--) {
            //System.out.println(i + ":" + visit[i]);
            if (maxSteps == visit[i]) {
                answer = i;
                break;
            }
        }
        System.out.println("answer:" + answer);
    }

    public static void dfs(int person) { // 人标号

        boolean flag = false;
        for (int i = 1; i < size; i++) {
            if (data[i][0] == person) {
                // if (visit[data[i][1]] == 0) { // 之前没有访问过
                if (visit[data[i][1]] == 0 || steps < visit[data[i][1]]) { // 之前没有访问过
                    visit[person] = steps;
                    steps++; // 走过步数增加
                    flag = true;
                    dfs(data[i][1]);
                    steps--; // 返回上一步步数减少
                }
            }
        }
        // dfs 出口
        if (!flag) {
            visit[person] = steps; // 当走到头时也要统计步数
            maxSteps = steps > maxSteps ? steps :maxSteps;
            return;
        }
    }
}
case1:
2 7 11 6 6 2 2 15 15 4 4 2 4 10 7 1 1 7 1 8 1 17 3 22 7 17
answer:10
case2:
2 7 11 6 6 2 2 15 15 4 4 2 4 10 7 1 1 7 1 8 1 17 3 22 7
answer:17
case3:
2 5 4 7 2 4 1 8 4 1 8 5 3 7 3 7 4 7 7 6
answer:5
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值