阿里2017暑期编程测试之关系

阿里编程测试之关系

昨天做了阿里内推的编程测试,题目大致意思如下:

定义一个关系对集合S = {(A,B),(B,J),(C,D),(E,F),(G,H),(H,I),(I,J)},每一个关系对之间的关系可以是同事,同学,老乡等。关系间的距离可以定义为到达对方所需的最小步数,即AB之间距离为1,AJ之间距离为2.请写一个函数,实现如下功能:给定两个人x和y,一个数字d,判断这两个人在距离d内存不存在关系。
输入输出示例:
A I 2 => false
A I 3 => true

首先我想到的就是用图去做,但是当时看到默认编辑器中提供了map,转念一想,那岂不是让我用map去做?只两个人x,y之间存不存在一条通路不就可以了吗?也就是:
x->x1->x2->x3->...->y,对其中任意的连续对p,q,存在map[p] = q。
我傻傻地这样做了。做完才发现,测试用例通不过,这时才想到,用普通的map方法,默认了关系是有向图,而事实上,关系是无向图。但是当时已经没多少时间了,我匆匆瞎改了一些东西就提交了。
今天我又复习了一下数据结构中图的知识,重新做了一遍,思路大概如下:

  • 先根据给定的关系,建立一张无向图,图可以用邻接矩阵或者邻接表来表示,我这里选用的是邻接矩阵,因为节点数不多,而且建立也方便。
  • 然后对指定结点进行遍历(不需要遍历所有结点),有深度优先遍历和广度优先遍历,应该都是可以选的,我选择的是深度优先实现,按理说广度优先应该更符合一点。但是也都差不多了。
  • 设置一个标志,用来标记有没有找到。给定距离d及目标,每次深度优先的时候减一,如果到0了还没找到,就返回;如果找到了就将标志位置为真。
  • 等到遍历完成之后,判断标志位置是否为真,如果是真,那么找到了,否则就是没找到,也就是说在制定距离内二者没有关系。

代码如下:

#include<map>
#include<iostream>

#define MAXSIZE 15

using namespace std;

struct Graph{
    char vex[MAXSIZE];
    int arcs[MAXSIZE][MAXSIZE];
    int arcNums,vexNums;
};

void initGraph(Graph &g){
    //因为题目中已经给出了图的基本信息,这里就直接用来初始化了
    g.arcNums = 7;
    g.vexNums = 10;
    //存储结点
    for(int i = 0;i<g.vexNums;i++)
        g.vex[i] = 'A'+i;

    //强行用map来初始化邻接矩阵
    map<int,int> mp;
    mp[0] = 1;  //A B 同事,同学等
    mp[1] = 9;  //B J 
    mp[2] = 3;  //C D 
    mp[4] = 5;  //E F
    mp[6] = 7;  //G H
    mp[7] = 8;  //H I
    mp[8] = 9;  //I J
    //先初始化为0
    for (int i = 0; i < g.vexNums; i++) {
        for (int j = 0; j < g.vexNums; j++) {
            g.arcs[i][j] = 0;
        }
    }
    //无向图是对称的
    for (int i = 0; i < g.vexNums; i++) {
        if (mp[i] != 0) {
            g.arcs[i][mp[i]] = g.arcs[mp[i]][i] = 1;
        }
    }
}

//全局访问数组
bool visited[MAXSIZE] = {false};

void dfs(const Graph &g,int i, int dis,char des,bool &flag){
    //普通的dfs,只不过加了距离判断和标志位
    visited[i] = true;
    //cout<<"Now visiting node: "<<g.vex[i]<<endl;
    for(int j = 0;j<g.vexNums;j++){
        //要保证每次循环时dis不被改变
        int temp = dis;
        if(temp!=0 && g.arcs[i][j]==1 && !visited[j]){
            if(g.vex[j]==des){
                flag = true;
                return;
            }
            else
                dfs(g,j,--temp,des,flag);
        }
    }
}

void dfsTraverse(Graph &g,int start,int dis,char des){
    bool flag = false;
    dfs(g,start,dis,des,flag);
    if(flag)
        cout<<"True"<<endl;
    else
        cout<<"False"<<endl;
}

int main(){
    Graph g;
    initGraph(g);
    char startc = 'A';
    char des = 'I';
    int dis = 3;
    cin>>startc>>des>>dis;
    int start = startc-'A';

    dfsTraverse(g,start,dis,des);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值