转发帖子链[CodeForces-522A]

Reposts[CodeForces-522A]

VK Cup 2015 - Qualification Round 1

时间限制 1000ms 内存限制  256MB

这道题主要是求最大遍历深度,不难想到用DFS解。这道题数据量不大,暴搜可以直接过,所以本身题目没啥难度,只是建图的时候要用map处理一下字符串和图的顶点的对应关系。但是自己的DFS写的真叫一个狗屎,索性好好分析一下DFS的整个过程,来作为这道题的题解。

在算法导论书中,给出了进行DFS所需要的必备的储存信息:

当前顶点需要一个前驱$v.π$,用来跟踪DFS结束时构成的深度优先树。,当前顶点被访问到的时间戳$v.d$和完全访问后染成黑色的时间戳$v.f$(实际上,$v.d$也可以理解为跟源节点到当前位置的距离有关,也就是和深度有关,而$v.f$是回溯时才记录,跟深度就不好相关了。),除此之外,还需要一个染色$v.color$,用来记录当前顶点的颜色。其实这个染色的属性是用来判断当前节点走没走过,在算导书中提及,染色节点只要包括两种颜色就行了,因此实际上只需要一个布尔值。

DFS的开始,是在给定的图$G(V,E)$中,选择每一个可能的顶点,也就是$∀u∈G.V$,依次进行DFS。二叉树的DFS遍历,其实就是图的DFS的特例,因为二叉树的起始顶点只有树根。在DFS过程中,设当前顶点为$u$,先将$u$染色为$black$($u.color=black$),然后选择所有有边连接的顶点$∀u′∈G:Adj[u]$,判断是否被染色,对于没有染色,也就是没有走过的顶点继续进行DFS,直到没有顶点可以走为止。没有顶点可以走,意味着所有的顶点都被染色了,或者直接这个顶点没有连接任何下一个顶点。实际上,在上述描述的DFS过程中,无需额外设置递归的出口,因为选择合法的$u′$已经暗含了递归出口。需要注意,当DFS子过程回溯到主体过程时,需要重置所有顶点的染色标记和前驱标记。

下面考虑具体实现的问题:一是图选择何种表示方法。通常情况下,稀疏图采用邻接表的方法,这样能够避免大量的空间浪费。因为采用邻接矩阵的方法,有$V$个顶点的图,就需要$V×V$的矩阵,也就是$V^2$的空间;并且搜索时,必须依次扫描当前顶点是不是存在着到别的顶点的边,因此总的时间复杂度是$O(V^2)$,在假定稀疏图$E<<V$的情况,邻接矩阵相较于邻接表的$O(V+E)$还是较慢的。对于邻接表中的表,通常的定义为链表,但是能够自由扩张的顺序数据结构都是可以的。因此我在做题的时候,采用了STL中的vector容器,来作为图的邻接表表示。至于染色属性的选择,既可以将图的每一个顶点定义成结构体,也可以单独设置数组,作为染色标记。我在这里采用了后一种的处理方法。

对于数组作为邻接表的表示方法,我一开始把下标搞混了,一直得不到正确的结果。以我写的DFS过程为例,id参数表示当前顶点,用一个循环遍历vector容器表示的邻接表寻找有边连接的下一个顶点,因此判断下一个顶点是否被染色时,gone数组的下标实际上是下一个顶点graph[id][i],而不是idi的任意一个,i在这里表示用vector容器实现的邻接表在当前为id的顶点所包含的相邻的第i个顶点。除此之外,试图将判重和记录深度用一个属性来表示,似乎并不可行。

下面给出我AC的完整代码,供参考。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<string>
 4 #include<vector>
 5 #include<map>
 6 #include<algorithm>
 7 using namespace std;
 8 map<string, int> mapper;
 9 vector<int> graph[205];
10 int gone[205];
11 int n;
12 int cnt = 0;
13 int ans = -2;
14 int proc(string & s)
15 {
16     for (int i = 0; i < s.size(); i++)
17         if (s[i] >= 'A'&&s[i] <= 'Z')s[i] += 32;
18     map<string, int>::iterator it = mapper.find(s);
19     if (it == mapper.end())
20     {
21         mapper.insert(pair<string, int>(s, cnt));
22         return cnt++;
23     }
24     return it->second;
25 }
26 void dfs(int id, int time)
27 {
28     gone[id] = 0;
29     for (int i = 0; i < graph[id].size(); i++)
30     {
31         if(gone[graph[id][i]]!=-1||graph[graph[id][i]].empty())
32         {
33             ans = max(ans, time + 1);
34             return;
35         }
36         dfs(graph[id][i], ++time);
37     }
38 }
39 int main()
40 {
41     cin >> n;
42     string tmp1, tmp2;
43     while (n--)
44     {
45         cin >> tmp1;
46         cin >> tmp2;
47         cin >> tmp2;
48         int id1 = proc(tmp1);
49         int id2 = proc(tmp2);
50         graph[id1].push_back(id2);
51     }
52     for (int i = 0; i < cnt; i++)
53     {
54         for (int j = 0; j < 205; j++)gone[j] = -1;
55         dfs(i, 0);
56     }
57     cout << ans + 1;
58     return 0;
59 }

 

 ,

原文地址:https://www.cnblogs.com/ggggg63/p/6767831.html