Topcoder 2017 TCO Algorithm Round 3A Hard

来源:互联网 发布:彩票数据分析预测软件 编辑:程序博客网 时间:2024/05/17 23:26

链接:

link

题意:

给一棵n个节点的树,有m个人,给每个人分配一个位置,满足一些限制:
如果以ri为根,aibi的LCA为xi

题解:

2-SAT。
考虑第i个人是否在子树j里建立一个点,然后怎么建边就很简单了。
注意树形结构的一些限制。
(其实应该可以把边数优化到和点数同阶,但是原题范围n2m能过,就没去写了)

代码:

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;const int MAXN = 255;const int MAXM = 125005;int id[MAXN][MAXN], lca[MAXN][MAXN], dep[MAXN], par[MAXN], ans[MAXN], scc[MAXM], chose[MAXM], d[MAXM], opp[MAXM], dfn[MAXM], num, tot, n;pii re[MAXM];vector <int> adj[MAXM], tre[MAXN], G[MAXM];inline void Addedge(int x, int y) { adj[x].pb(y); adj[y ^ 1].pb(x ^ 1); }inline void Dfs(int x){    static int low[MAXM], st[MAXM], tp, tim;    dfn[x] = low[x] = ++ tim;    st[++ tp] = x;    for (auto y : adj[x])        if (!dfn[y])            Dfs(y), low[x] = min(low[x], low[y]);        else if (!scc[y])            low[x] = min(low[x], dfn[y]);    if (dfn[x] == low[x])    {        num ++;        for (int t = -1; t ^ x; scc[t = st[tp --]] = num);    }}inline void Build(){    for (int x = 0; x < tot << 1; x ++)        for (auto y : adj[x])            if (scc[x] ^ scc[y])                G[scc[y]].pb(scc[x]), d[scc[x]] ++;}inline void Top(){    static int q[MAXM], ql, qr;    for (int i = 1; i <= num; i ++)        if (!d[i])            q[++ qr] = i;    while (ql ^ qr)    {        int x = q[++ ql];        if (~chose[x])            continue;        chose[x] = 1, chose[opp[x]] = 0;        for (auto y : G[x])            if (!-- d[y])                q[++ qr] = y;    }}inline bool Chk(){    for (int i = 0; i < tot << 1; i ++)        if (!dfn[i])            Dfs(i);    for (int i = 0; i < tot; i ++)        if (scc[i << 1] == scc[i << 1 | 1])            return false;    for (int i = 1; i <= num; i ++)        chose[i] = -1;    Build();    for (int i = 0; i < tot; i ++)        opp[scc[i << 1]] = scc[i << 1 | 1], opp[scc[i << 1 | 1]] = scc[i << 1];    Top();    for (int i = 0; i < tot; i ++)        if (chose[scc[i << 1]])            ans[re[i].xx] = max(ans[re[i].xx], re[i].yy - 1);    return true;}class HiddenRabbits{    public:        vector <int> whereAreTheRabbits(vector <int> p, int m, vector <int> r, vector <int> a, vector <int> b, vector <int> x)        {            n = p.size() + 1;            for (int i = 2; i <= n; i ++)                par[i] = p[i - 2] + 1, tre[par[i]].pb(i);            for (int i = 2; i <= n; i ++)                dep[i] = dep[i - 1] + 1;            for (int i = 1; i <= n; i ++)                for (int j = 1; j <= n; j ++)                    if (i == j)                        lca[i][j] = i;                    else if (dep[i] > dep[j])                        lca[i][j] = lca[par[i]][j];                    else                        lca[i][j] = lca[i][par[j]];            for (int i = 1; i <= m; i ++)                for (int j = 1; j <= n; j ++)                    id[i][j] = tot, re[tot ++] = mp(i, j);            for (int i = 1; i <= m; i ++)                for (int j = 2; j <= n; j ++)                    Addedge(id[i][j] << 1, id[i][par[j]] << 1);            for (int i = 1; i <= m; i ++)                adj[id[i][1] << 1 | 1].pb(id[i][1] << 1);            for (int i = 1; i <= m; i ++)                for (int x = 0; x <= n; x ++)                    for (auto y : tre[x])                        for (auto z : tre[x])                            if (y > z)                                Addedge(id[i][y] << 1, id[i][z] << 1 | 1);            int k = r.size();            for (int i = 0; i < k; i ++)            {                int R = r[i] + 1, A = a[i] + 1, B = b[i] + 1, X = x[i] + 1;                if (lca[R][X] ^ X)                {                    adj[id[A][X] << 1 | 1].pb(id[A][X] << 1);                    adj[id[B][X] << 1 | 1].pb(id[B][X] << 1);                    for (auto Y : tre[X])                        Addedge(id[A][Y] << 1, id[B][Y] << 1 | 1);                }                else                {                    if (R ^ X)                    {                        int cur = R;                        while (par[cur] ^ X)                            cur = par[cur];                        adj[id[A][cur] << 1].pb(id[A][cur] << 1 | 1);                        adj[id[B][cur] << 1].pb(id[B][cur] << 1 | 1);                    }                    for (auto Y : tre[X])                        Addedge(id[A][Y] << 1, id[B][Y] << 1 | 1);                    Addedge(id[A][X] << 1 | 1, id[B][X] << 1);                }            }            if (!Chk())                return vector <int> ();            return vector <int> (ans + 1, ans + m + 1);        }};
原创粉丝点击