每次到了晚上都无法静下心来写题目,不如写篇博客,总结一天的学习。
今天一天,首先回顾了昨晚Codeforces的几道题目。恕本蒟蒻太菜,实在无法写出来后面两道题目。
然后偶然发现很久之前的一道题目还没写,就顺手写了。然后便开始了今天的学习。
今天主要学习的问题是连通图的一些问题。
第一个问题就是强连通分量的求解。这一部分事实上我看了挺多的博客还有资料都没有看的太懂,最后跟着某篇博客里面的模板敲了一遍Tarjan算法。算是稍微懂了一些。
对于强连通分量的问题,本来我只能够用最暴力的方法写出来,是不是正确的还不好说,但是时间复杂度确实是相当的高的。而Tarjan算法,能够在O(V+E)的时间复杂度里面求解出强连通分量。不得不说真是非常神奇。
说起来强联通分量的问题也是深度优先搜索的一个应用吧。
设两个数组,dfn[i]和low[i]分别表示图的第i个点被访问的次序和第i个点能够回退到的最小的一个点。
关于这部分的解释这个博客说的的确还是很可以的。最起码我大概是理解了一些...
然后通过dfs搜索,就可以求出来强连通分量。
然后就是题目,今天做了两题关于强连通分量的题目,
一题是hdu 1269。
中文题直接上代码了。
#include <stack>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 10005;
const int maxm = 100005;
typedef struct node {
int to, nxt;
node(int a = 0, int b = 0) {
to = a; nxt = b;
}
}Edge;
stack<int> s; //存储已遍历的节点
Edge edge[maxm]; //链式前向星存储边的信息
int tot, head[maxn]; //链式前向星存储边的信息
int InComponet[maxn]; //记录每个点在哪个强联通分量中
vector<int> Componet[maxn]; //记录强联通分量结果
int n, m, index, ComponetNumber; //点的数量、边的数量、索引号、强联通分量数目
int dfn[maxn], low[maxn], inStack[maxn]; //深度优先搜索访问次序、能追溯到的最早的次序、检查是否在栈中(0代表不在,1代表访问过且不在栈中,2代表在栈中)
void add(int u, int v) {
edge[tot] = Edge(v, head[u]);
head[u] =