数据结构学习笔记(七)--图

  1. 图的存储方式一般分为邻接矩阵与邻接链表。矩阵操作简单,但稀疏图时采用链表效率更高。

  2. 图的遍历:DFS(用递归实现) BFS(用队列实现,类似于树的层序遍历!)

    注意什么时候使用DFS什么时候使用BFS更好?
    **如果估计目标顶点离开起始顶点不会太远,那么选择广度优先遍历是比较合适的,因为广度优先是一种由近及远的搜索策略;
    如果估计目标顶点与起始顶点没有太大的关系,那么选择深度优先遍历是比较合适的,深度优先是通过邻接点尽快接近较远目标的搜索策略。
    所以,大多数题目还是用广度优先为佳,毕竟深度优先是个递归的程序,而广度优先可以写成循环。
    适合用深度的,大概就是上面所说的,已经对目标定点的位置有了模糊的印象,并经判断合适。**

  3. 解决实际问题时,有必要每次都把图的结构表示成矩阵或链表吗?其实不必。图只是一个抽象概念,方便我抽象实际问题,有时候世界用一个二维数组表示邻接矩阵就可以完全解决问题了。

    如练习中的列出连通子集

#include <cstdio>

#define N 15

void ListComponentsWithDFS();
void ListComponentsWithBFS();
void DFS(int V);
void BFS(int V);
void InitVisit(void);

int n;
bool Visited[N];
int G[N][N] = {0};

int main()
{
    int E;

    scanf("%d%d", &n, &E);
    for (int i = 0; i < E; i++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        G[b][a] = G[a][b] = 1;
    }
    ListComponentsWithDFS();
    InitVisit();
    ListComponentsWithBFS();

    return 0;
}

void ListComponentsWithDFS()
{
    for (int V = 0; V < n; V++)
        if (!Visited[V])
        {
            printf("{ ");
            DFS(V);
            printf("}\n");
        }
}

void ListComponentsWithBFS()
{
    for (int V = 0; V < n; V++)
        if (!Visited[V])
        {
            printf("{ ");
            BFS(V);
            printf("}\n");
        }
}

void DFS(int V)
{
    Visited[V] = true;
    printf("%d ", V);
    for (int i = 0; i < n; i++)
    {
        if (G[V][i] && !Visited[i])
            DFS(i);
    }
}

void BFS(int V)
{
    const int MAX_SIZE = 100;
    int Queue[MAX_SIZE];
    int first = -1, last = -1;

    Queue[++last] = V;      //入队
    Visited[V] = true;
    while (first < last)    //当队不为空时
    {
        int F = Queue[++first];     //出队
        printf("%d ", F);
        for (int i = 0; i < n; i++)
        {
            if (G[F][i] && !Visited[i])
            {
                Queue[++last] = i;      //入队
                Visited[i] = true;
            }
        }
    }
}

void InitVisit()
{
    for (int i = 0; i < N; i++)
        Visited[i] = false;
}

习题:拯救007

利用遍历连通子集的思想。
Saving James Bond - Easy Version

/*拯救007*/
/*by zoe*/
#include <cmath>
#include <cmath>
#include <cstdio>
#include <fstream>
#include <iostream>
#define YES 1
#define NO 0
using namespace std;
struct Point {
  int num;
  int x;
  int y;
  Point &operator=(Point P) {
    num = P.num;
    x = P.x;
    y = P.y;
    return *this;
  }
};

Point M[102][102];
Point P[102];
bool visited[102];
int nu;
// int ne;
int D;

bool Jump(Point P, Point V) {
  if (sqrt((P.x - V.x) * (P.x - V.x) + (P.y - V.y) * (P.y - V.y)) < D)
    return true;
  else
    return false;
}

bool FirstCanJump(Point P) {
  // printf("judge first can jump:%f\n", sqrt(P.x * P.x + P.y * P.y));
  if (sqrt(P.x * P.x + P.y * P.y) < D)
    return true;
  else
    return false;
}

bool IsSafe(Point P) {
  if (fabs(P.x - 50) < D || fabs(P.y - 50) < D)
    return true;
  else
    return false;
}

int DFS(Point Pv) {
  // printf("DFS start!\n");
  int answer;
  Point V;
  visited[Pv.num] = true;
  if (IsSafe(Pv))
    answer = YES;
  else {
    // printf("not the end\n");
    for (int i = 0; i < nu; i++) {
      V = P[i];
      if (!visited[V.num] && Jump(Pv, V)) {
        answer = DFS(V);
        if (answer == YES)
          break;
      }
    }
  }
  return answer;
}

void Save007(Point Pv) {

  int answer;
  for (int i = 0; i < nu; i++) {
    Pv = P[i];
    if (!visited[Pv.num] && FirstCanJump(Pv)) {
      // printf("first can jump\n");
      answer = DFS(Pv);
      if (answer == YES)
        break;
    }
    // Pv = P[i];
  }
  if (answer == YES)
    printf("Yes\n");
  else
    printf("No\n");
}

int main() {
  int i;

  // string S;

  cin >> nu >> D;
  // cout << nu << " " << D << endl;
  if (nu <= 0)
    printf("No\n");
  for (i = 0; i < nu; i++)
    P[i].num = i;

  for (i = 0; i < nu; i++) {
    scanf("%d%d\n", &P[i].x, &P[i].y);
    // cout << i << endl;
    // cout << i << " " << P[i].x << " " << P[i].y << endl;
  }
  for (i = 0; i < nu; i++)
    visited[i] = 0;

  // cout << 0 << " " << P[0].x << " " << P[0].y << endl;

  Save007(P[0]);
  /*int i, a[6];
  for (i = 0; i < 5; i++)
    cin >> a[i];
  cout << a[4] << endl;*/
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值