图的遍历 | 1131地铁图: dfs复杂模拟题

这题在搞清楚思路绕过坑后,还是可以写的出通过sample data的代码的。但是不能AC,让我很气。

最后查清原因:还是对dfs本质理解的不够。

wa代码:

vis[s]=1;
dfs(s,e,0);

殊不知本题有多个查询数据。如果只调用一遍还可以蒙混过关,但是这样的错误必然导致wa

ac代码:

vis[s]=1;
dfs(s,e,0);
vis[s]=0;

参考柳诺博客修改的AC代码:

#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>

#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 10000
#define MAX 0x06FFFFFF
#define V vector<int>

using namespace std;

vector<int> g[LEN];
int line[LEN][LEN];
int vis[LEN];
vector<int> path;
vector<int> ans;
int min_d=MAX;
int min_ls=MAX;

int N,M,K;

int calc_ls(){
    int cnt=-1,preLine=0;
    for(int i=1;i<path.size();i++){
        if(line[path[i-1]][path[i]]!=preLine) cnt++;
        preLine=line[path[i-1]][path[i]];
    }
    return cnt;
}

void dfs(int s,int e,int d){
    if(s==e){
        int ls=calc_ls();
        if(d<min_d || (d==min_d && ls<min_ls)){
            min_d=d;
            min_ls=ls;
            ans=path;
        }
        return;
    }
    int i;
    FF(i,g[s].size()){
        int o=g[s][i];
        if(!vis[o]){
            vis[o]=1;
            path.push_back(o);
            dfs(o,e,d+1);
            vis[o]=0;
            path.pop_back();
        }
    }

}

void printLine(){
    int s=ans[0];
    int preL=0;
    int i;
    F(i,1,ans.size()){
        if(line[ans[i-1]][ans[i]]!=preL){
            if(preL) printf("Take Line#%d from %04d to %04d.\n",preL,s,ans[i-1]);
            s=ans[i-1];
            preL=line[ans[i-1]][ans[i]];
        }
    }
    printf("Take Line#%d from %04d to %04d.\n",preL,s,ans[i-1]);
}

int main(){
//    freopen("1131.txt","r",stdin);
    int s,e,i,j;
    I("%d",&N);
    F(i,1,N+1){
        int pre,p=-1;
        I("%d",&M);
        while(M--){
            pre=p;
            I("%d",&p);
            if(pre>=0){
                g[p].push_back(pre);
                g[pre].push_back(p);
                line[p][pre]=i;
                line[pre][p]=i;
            }
        }
    }
    I("%d",&K);
    while(K--){
        min_d=MAX;
        min_ls=MAX;
        path.clear();
        ans.clear();
        I("%d%d",&s,&e);
        path.push_back(s);
        vis[s]=1;
        dfs(s,e,0);
        vis[s]=0;
        O("%d\n",min_d);
        printLine();
    }
    return 0;
}

在自己思路上修改的AC代码:(个人认为比柳诺的好理解)

  1 #include <stdio.h>
  2 #include <memory.h>
  3 #include <math.h>
  4 #include <string>
  5 #include <vector>
  6 #include <set>
  7 #include <stack>
  8 #include <queue>
  9 #include <algorithm>
 10 #include <map>
 11
 12
 13 #define I scanf
 14 #define OL puts
 15 #define O printf
 16 #define F(a,b,c) for(a=b;a<c;a++)
 17 #define FF(a,b) for(a=0;a<b;a++)
 18 #define FG(a,b) for(a=b-1;a>=0;a--)
 19 #define LEN 10000
 20 #define MAX 0x06FFFFFF
 21 #define V vector<int>
 22
 23 using namespace std;
 24
 25 vector<int> g[LEN];
 26 int line[LEN][LEN];
 27 int vis[LEN];
 28 vector<int> path;
 29 vector<int> ans;
 30 int min_d=MAX;
 31 int min_ls=MAX;
 32
 33 int N,M,K;
 34
 35 void dfs(int s,int e,int d,int l,int ls){
 36     if(s==e){
 37         if(d<min_d || (d==min_d && ls<min_ls)){
 38             min_d=d;
 39             min_ls=ls;
 40             ans=path;
 41         }
 42         return;
 43     }
 44     int i;
 45     FF(i,g[s].size()){
 46         int o=g[s][i];
 47         if(!vis[o]){
 48             vis[o]=1;
 49             path.push_back(o);
 50             int nl=line[s][o];
 51             int nls=ls;
 52             if(l==0){    //初始结点
 53                 nls=1;
 54             }else{
 55                 if(nl!=l) nls++;
 56             }
 57             dfs(o,e,d+1,nl,nls);
 58             vis[o]=0;
 59             path.pop_back();
 60         }
 61     }
 62
 63 }
 64
 65 void printLine(){
 66     int s=ans[0];
 67     int preL=line[s][ans[1]];
 68     int i;
 69     F(i,1,ans.size()){
 70         if(line[ans[i-1]][ans[i]]!=preL){
 71             printf("Take Line#%d from %04d to %04d.\n",preL,s,ans[i-1]);
 72             s=ans[i-1];
 73             preL=line[ans[i-1]][ans[i]];
 74         }
 75     }
 76     printf("Take Line#%d from %04d to %04d.\n",preL,s,ans[i-1]);
 77 }
 78
 79 int main(){
 80 //    freopen("1131.txt","r",stdin);
 81     int s,e,i,j;
 82     I("%d",&N);
 83     F(i,1,N+1){
 84         int pre,p=-1;
 85         I("%d",&M);
 86         while(M--){
 87             pre=p;
 88             I("%d",&p);
 89             if(pre>=0){
 90                 g[p].push_back(pre);
 91                 g[pre].push_back(p);
 92                 line[p][pre]=i;
 93                 line[pre][p]=i;
 94             }
 95         }
 96     }
 97     I("%d",&K);
 98     while(K--){
 99         min_d=MAX;
100         min_ls=MAX;
101         path.clear();
102         ans.clear();
103         I("%d%d",&s,&e);
104         vis[s]=1;
105         dfs(s,e,0,0,0);
106         vis[s]=0;
107         O("%d\n",ans.size());
108         ans.insert(ans.begin(),s);
109         printLine();
110     }
111     return 0;
112 }

注意点:

① 38 39 行,对维护的最小距离和最小换乘次数进行更新,不要写错(我开始写成了d=min_d ,查了很久的错,蠢哭……)

② 99 100 行,将最小距离和最小换乘次数重新初始化为INF。

③ 106 行,牢记 dfs 结构

原文地址:https://www.cnblogs.com/TQCAI/p/8543161.html

时间: 2024-10-13 14:07:43

图的遍历 | 1131地铁图: dfs复杂模拟题的相关文章

图的遍历(bfs 和dfs)

BFS的思想: 从一个图的某一个顶点V0出发,首先访问和V0相邻的且未被访问过的顶点V1.V2.……Vn,然后依次访问与V1.V2……Vn相邻且未被访问的顶点.如此继续,找到所要找的顶点或者遍历完整个图. 由此可以看出,用BFS进行搜索所搜索的顶点都是按深度进行扩展的,先找到到V0距离为1的所有顶点,然后找到距离V0为2的顶点……所以BFS所搜索到的都是最短的路径. 由于要将距离V0为d(d>0)的且未被方位的点都记录起来,我们采用队列这种数据结构.队列的特点是先进先出(FIFO),从某个顶点出

图的遍历(BFS、DFS的邻接矩阵和邻接表实现)

当年老师给我们讲这里的时候,讲的真是云里雾里的. .其实画个图就很容易理解的事情,为什么扯那么远 我觉得 DFS其实就是树的先序遍历的强化版本 BFS是层序遍历的强化 只不过 图的实现方式比较多元化 而且不像二叉树有明确的根 操作起来相对难一些 理论其实很好理解 就是具体操作起来 每次都很晕的样子 眼高手低了又. 图的遍历是指从图中的任一顶点出发,对图中的所有顶点访问一次且只访问一次.图的遍历操作和树的遍历操作功能相似.图的遍历是图的一种基本操作,图的许多其它操作都是建立在遍历操作的基础之上.

PAT Advanced 1034 Head of a Gang (30) [图的遍历,BFS,DFS,并查集]

题目 One way that the police finds the head of a gang is to check people's phone calls. If there is a phone call between A and B, we say that A and B is related. The weight of a relation is defined to be the total time length of all the phone calls mad

PAT Advanced 1076 Forwards on Weibo (30) [图的遍历,BFS,DFS]

题目 Weibo is known as the Chinese version of Twitter. One user on Weibo may have many followers, and may follow many other users as well. Hence a social network is formed with followers relations. When a user makes a post on Weibo, all his/her followe

算法导论--图的遍历(DFS与BFS)

转载请注明出处:勿在浮沙筑高台http://blog.csdn.net/luoshixian099/article/details/51897538 图的遍历就是从图中的某个顶点出发,按某种方法对图中的所有顶点访问且仅访问一次.为了保证图中的顶点在遍历过程中仅访问一次,要为每一个顶点设置一个访问标志.通常有两种方法:深度优先搜索(DFS)和广度优先搜索(BFS).这两种算法对有向图与无向图均适用. 以下面无向图为例: 1.深度优先搜索(DFS) 基本步骤: 1.从图中某个顶点v0出发,首先访问v

图的遍历 - 数据结构

图的遍历 - 数据结构 概述 图的遍历是指从图中的任一顶点出发,对图中的所有顶点访问一次且只访问一次.图的遍历操作和树的遍历操作功能相似.图的遍历是图的一种基本操作,图的其它算法如求解图的连通性问题,拓扑排序,求关键路径等都是建立在遍历算法的基础之上. 由于图结构本身的复杂性,所以图的遍历操作也较复杂,主要表现在以下四个方面:① 在图结构中,没有一个“自然”的首结点,图中任意一个顶点都可作为第一个被访问的结点.② 在非连通图中,从一个顶点出发,只能够访问它所在的连通分量上的所有顶点,因此,还需考

C#与数据结构--图的遍历

C#与数据结构--图的遍历 8.2 图的存储结构 图 的存储结构除了要存储图中各个顶点的本身的信息外,同时还要存储顶点与顶点之间的所有关系(边的信息),因此,图的结构比较复杂,很难以数据元素在存储区 中的物理位置来表示元素之间的关系,但也正是由于其任意的特性,故物理表示方法很多.常用的图的存储结构有邻接矩阵.邻接表.十字链表和邻接多重表. 8.2.1  邻接矩阵表示法 对于一个具有n个顶点的图,可以使用n*n的矩阵(二维数组)来表示它们间的邻接关系.图8.10和图8.11中,矩阵A(i,j)=1

第五章 图的遍历(深度遍历,广度遍历,城市地图,最少转机)

深度和广度优先搜索: 单词分解:首先是搜索 深度和广度:是针对图的遍历而言的 图:由顶点和边组成 图的遍历:把图中每一个顶点都访问一次 一: 输入: 5 5(顶点数,边数) 1 2 1 3 1 5 2 4 3 5 输出: 1 2 4 3 5 (按时间戳输出)深度遍历 1 2 3 5 4 (按时间戳输出)广度遍历 1 #include <stdio.h> 2 int map[10][10], book[10], n, m,sum; 3 void dfs(int cur) 4 { 5 int i;

数据结构与算法10—图的遍历

图的遍历 1. 在图中有回路,从图中某一顶点出发访问图中其它顶点时,可能又会回到出发点,而图中可能还剩余有顶点没有访问到. 2. 我们可以设置一个全局型标志数组visited来标志某个顶点是否被访问过,未访问的值为0,访问过的值为1. 3. 图的遍历有两种方法:深度优先搜索遍历(DFS).广度优先搜索遍历(BFS). 深度优先搜索 深度优先搜索思想 首先访问顶点i,并将其访问标记置为访问过,即visited[i] =1: 然后搜索与顶点i有边相连的下一个顶点j,若j未被访问过,则访问它,并将j的