前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >51Nod-1618-树或非树

51Nod-1618-树或非树

作者头像
f_zyj
发布2018-01-09 11:00:24
5170
发布2018-01-09 11:00:24
举报

ACM模版

描述

描述
描述
描述
描述

题解

这是 CFCF 上的一道原题,没有啥思路,于是找来一下题解,找到了一个远古的博客(jasonzhu8’s blog),里面有这个题的题解,然而他的代码写得实在让我难受,并且有一点我不是特别理解,但是依然是大佬。

大佬题解:

描述
描述

这个题解的第一句我无法理解,题目中说给定一个 nn 点 nn 边的无向图,可是并没有说是 一棵树 + 一条边 啊,这么强的条件,我不理解该大佬从何悟出,难道说是因为数据太水了,误打误撞的吗?这个问题我纠结了一天,怎么想也想不通为何得出这样的结论,当然,如果是建立在这个强条件下,那么后边的题解就很容易理解了。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXN = 100005;

int n, m;
int cnt1, cnt2, tmp, mb, mdb, ans;
int d[MAXN], z[MAXN], g[MAXN], o[MAXN];
int pre[MAXN], pre_[MAXN], p[MAXN << 1], nxt[MAXN << 1];

struct node
{
    int g, cnt;
    int l[MAXN], r[MAXN];
    int z[MAXN], a[MAXN];
    int x[MAXN], y[MAXN];
    int pre[MAXN], root[MAXN];

    void put(int i, int j)
    {
        if (i && j)
        {
            z[i] = !z[i];
            a[i] = !a[i];
            swap(x[i], y[i]);
        }
    }

    void lazy(int i)
    {
        put(l[i], z[i]);
        put(r[i], z[i]);
        z[i] = 0;
    }

    void rt(int i, int j)
    {
        if (l[i] == j)
        {
            l[i] = r[j];
            pre[r[j]] = i;
            r[j] = i;
        }
        else
        {
            r[i] = l[j];
            pre[l[j]] = i;
            l[j] = i;
        }
        root[j] = root[i];
        root[i] = 0;
        if (l[pre[i]] == i)
        {
            l[pre[i]] = j;
        }
        else if (r[pre[i]] == i)
        {
            r[pre[i]] = j;
        }

        pre[j] = pre[i];
        pre[i] = j;
        update(i);
        update(j);
    }

    void splay(int i, int j)
    {
        if (root[i])
        {
            lazy(i);
        }
        while (!root[i])
        {
            lazy(pre[i]);
            lazy(i);
            rt(pre[i], i);
        }
        if (j)
        {
            root[g = r[i]] = 1;
            r[i] = 0;
            update(i);
        }
    }

    void update(int i)
    {
        x[i] = x[l[i]] + x[r[i]] + a[i];
        y[i] = y[l[i]] + y[r[i]] + 1 - a[i];
    }

    void access(int i)
    {
        splay(cnt = i, 1);
        while (pre[i])
        {
            splay(cnt = pre[i], 1);
            r[cnt] = 1;
            rt(cnt, i);
        }
    }

    void cover(int i)
    {
        access(i);
        splay(tmp, 0);
        ans += y[r[tmp]] - x[r[tmp]];
        put(r[tmp], 1);
    }
} tree;

void link(int a, int b)
{
    nxt[++cnt1] = d[a];
    d[a] = cnt1;
    p[cnt1] = b;
}

int find(int i)
{
    return (pre_[i] == i) ? i : pre_[i] = find(pre_[i]);
}

void dfs1(int i, int h)
{
    z[++cnt1] = i;
    o[i] = cnt1;
    for (int k = d[i], j = p[k]; k; k = nxt[k], j = p[k])
    {
        if ((h ^ k) != 1)
        {
            if (o[j])
            {
                mb = k;
                for (int l = o[j]; l <= cnt1; l++)
                {
                    g[++cnt2] = z[l];
                }
            }
            else
            {
                dfs1(j, k);
            }
        }
    }
    cnt1--;
}

void dfs2(int i, int h)
{
    for (int k = d[i], j = p[k]; k; k = nxt[k], j = p[k])
    {
        if ((h ^ k) != 1 && ((k ^ mb) > 1))
        {
            pre[j] = i;
            dfs2(j, k);
        }
    }
}

template <class T>
inline void scan_d(T &ret)
{
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9')
    {
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}

int main()
{
    scan_d(n);
    scan_d(m);

    cnt1 = 1;
    int a, b, mdb = 0;
    for (int i = 1; i <= n; i++)
    {
        scan_d(a);
        scan_d(b);
        link(a, b);
        link(b, a);
    }

    cnt1 = 0;
    dfs1(1, 0);
    dfs2(g[1], 0);
    for (int i = 0; i < MAXN; i++)
    {
        o[i] = 0;
    }
    for (int i = 1; i <= cnt2; i++)
    {
        o[g[i]] = i;
    }
    for (int i = 1; i <= n; i++)
    {
        pre_[i] = (o[i]) ? i : pre[i];
    }
    for (int i = 1; i <= n; i++)
    {
        find(i);
    }
    for (int i = 1; i <= n; i++)
    {
        tree.pre[i] = pre[i];
        tree.y[i] = tree.root[i] = 1;
    }

    g[0] = g[cnt2];
    tmp = g[cnt2 + 1] = g[1];
    while (m--)
    {
        scan_d(a);
        scan_d(b);
        int Fa = pre_[a], Fb = pre_[b];
        int d1 = abs(o[Fa] - o[Fb]);
        int g1, g2;
        if (o[Fa] < o[Fb])
        {
            g1 = g[o[Fa] + 1];
            g2 = g[o[Fa] - 1];
        }
        else
        {
            g1 = g[o[Fa] - 1];
            g2 = g[o[Fa] + 1];
        }

        tree.cover(a);
        tree.cover(b);
        if (d1 > cnt2 - d1 || ((d1 == cnt2 - d1) && g1 > g2))
        {
            mdb = !mdb;
            if (mdb)
            {
                ans++;
            }
            else
            {
                ans--;
            }
            tree.cover(g[cnt2]);
        }

        tree.access(g[cnt2]);
        int al = tree.x[g[cnt2]] + mdb == cnt2;

        printf("%d\n", n - ans + al);
    }

    return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年09月29日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 描述
  • 题解
  • 代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档