【2017.9.16周总结】

来源:互联网 发布:淘宝下载 编辑:程序博客网 时间:2024/06/04 19:22

Tarjan与缩点

这周做了不少需要先缩点的题。本来10分钟打出来的Tarjan模板,结果缩点各种错。以下都是血与泪的教训

  1. 关于Tarjan中的易错点:
    • 遇到未访问的点则用对方的low更新自己的low
    • 遇到访问过且仍在栈中的点才用对方的dfn更新low
      这两种情况并不互为补集,不能写成一个if-else
  2. 重新连边要考虑是否允许重边
    若要过滤重边,最好用set来存边,用rang-based loop遍历
    自环一般都要过滤:if (group[u] != group[v]) addedge(u,v);

  3. 做任何拓补序问题之前,先查看题目是否保证DAG,否则需用Tarjan缩点

点分治

最基础的静态点分治框架大概长这个样子:

bool vis[] = {};int size[], max[], son[];   //son[x]表示x的重儿子int dfssize(int x, int fa) {    //dfs处理以上3个数组    //遇到已vis就不再前进了。即 if (!vis[v] && v != fa)}dfs(int x, int fa, ...);cal(int x, ...);void divide(int x) {    int Size = dfssize(x,0); //x只是一个入口。这个函数为找root做铺垫    int root = x;    while (max[root]] > Size/2) //找root        root = son[root];    dfs(root,...); //解决关于整块的问题。通常先由dfs把信息(如dis)记录到一个数组或数据结构中,    cal(root,...); //再由cal()进行一些排序、统计等操作。    vis[root] = true;    for_each e(root, v) {        dfs(v,...); //需要扣除当路径两端出自同一子树的情况        cal(v,...); //dfs时慑于vis[root]的阻拦,自然不会越出子树    }}
原创粉丝点击