[NOI2017] game --2-sat

Face questions

  Bzoj4945

Resolve

  A very interesting 2-sat title

  At first I wanted to side, and I want to build a map for each three points representing the A, B, C car, and then found not even side (that is, to dish did not see how this question with a 2-sat) , then looked at the idea of ​​their own to get out of the code, I think carefully, this problem is very clever

  If you build a map of each three points, because the d <= 8, nearly $ \ frac {1} {3} $ would be a waste of points, so we can not delete the selected point, most of the maps are only two points a. At this time it is not considered the presence of x, so all maps only two points in two selected map points as a choice, there will be many restrictions relations, then obviously the 2-sat up. Consider how the title quadruple $ (i, h_ {i}, j, h_ {j}) $ connected edges, of course, with different situations, it is assumed point $ I $ Representative $ h_ {i} $, the point $ i '$ $ $ i is a point of the image point, point to point $ J $ $ j' $ Similarly, if dot $ i $ not selected just $ h_ {i} $, it is not even edge; if $ i $ dot can choose $ h_ {i} $ but $ j $ dot can not choose $ h_ {j} $, then force the $ i $ dot alternative to $ h_ {i} that point $ except, that is, $ i \ rightarrow i '$; if $ I $ ID can be selected from $ h_ {i} $ and $ J $ The ID can be selected from $ h_ {j} $, then $ i \ rightarrow j $, $ j' \ rightarrow i ' $ (contrapositive proposition). Figure end to this construction, the rest is tarjan, and part of the classification can be discussed in conjunction with the following look at the code, I wrote a work function within

  Then there's the presence of x, d is small, consider a violent enumerate every x map of the car, we have built a map of Figure 2-sat two cars, then enumerate every one x map to elect two cars, because the x in Figure 3 is selected vehicles a car, so each one has two x diagram election law in order to cover the running x chart three kinds of car, I used (a, C), and (B, C), so there is no case where an exhaustive enumeration of x in FIG. Enumeration time $ 2 ^ {d} $, each time re-built FIG ran Tarjan, so the total time complexity is $ O (2 ^ {d} (n + m)) $

  Special Judge's presence so I have not seen a sample or AC

 Code:

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 50004;

template<class T>
inline void read(T &re)
{
    T fl = 1;char c;
    while((c=getchar())&&(c<'0'||c>'9'))if(c=='-'1) in = -;
    re=c-'0';
    while((c=getchar())&&(c>='0'&&c<='9'))re=(re<<3)+(re<<1)+c-'0';
    re*=fl;
}

int n, m, d, rel[2][maxn];//A:1, B:2, C:3
char s[maxn];

int cnt, timer, top, stak[maxn<<1], dfn[maxn<<1], low[maxn<<1], bel[maxn<<1], xpos[10];
bool vis[maxn<<1];
vector<int> G[maxn<<1];

struct requir{
    int a, b;
    char ca, cb;
}req[maxn<<1];

void tarjan(int x)
{
    low[x] = dfn[x] = ++timer;
    stak[++top] = x;
    vis[x] = 1;
    for(unsigned int i = 0; i < G[x].size(); ++i)
    {
        int id = G[x][i];
        if(!dfn[id])
        {
            tarjan(id);
            low[x] = min(low[x], low[id]);
        }
        else if(vis[id])
            low[x] = min(low[x], dfn[id]);
    }
    if(dfn[x] == low[x])
    {
        cnt++;
        int t;
        do
        {
            t = stak[top--];
            vis[t] = 0;
            bel[t] = cnt;
        }
        while(t != x);
    }
}

bool work()
{
    timer = cnt = 0;
    for(int i = 1; i <= (n<<1); ++i)
    {
        bel[i] = dfn[i] = low[i] = 0;
        G[i].clear();
    }
    for(int i = 1; i <= m; ++i)
    {
        if(s[req[i].a] == req[i].ca)
            continue;
        if(s[req[i].b] == req[i].cb)
        {
            int x = (rel[1][req[i].a] + 'a' - 1 == req[i].ca);
            if(x == 1)
                G[req[i].a+n].push_back(req[i].a);
            else
                G[req[i].a].push_back(req[i].a+n);
        }
        else
        {
            int x = (rel[1][req[i].a] + 'a' - 1 == req[i].ca);
            int y = (rel[1][req[i].b] + 'a' - 1 == req[i].cb);
            if(x == 1)
            {
                if(y == 1)
                {
                    G[req[i].a+n].push_back(req[i].b+n);
                    G[req[i].b].push_back(req[i].a);
                }
                else
                {
                    G[req[i].a+n].push_back(req[i].b);
                    G[req[i].b+n].push_back(req[i].a);    
                }
            }
            else
            {
                if(y == 1)
                {
                    G[req[i].a].push_back(req[i].b+n);
                    G[req[i].b].push_back(req[i].a+n);
                }
                else
                {
                    G[req[i].a].push_back(req[i].b);
                    G[req[i].b+n].push_back(req[i].a+n);    
                }
            }
        }
    }
    for(int i = 1; i <= (n<<1); ++i)
        if(!dfn[i])
            tarjan(i);
    for(int i = 1; i <= n; ++i)
        if(bel[i] == bel[i+n])
            return 0;
    return 1;
}

void dfs(int x)
{
    if(x > d)
    {
        bool fl = work();
        if(fl)
        {
            for(int i = 1; i <= n; ++i)
                printf("%c", rel[bel[i] > bel[i+n]][i] + 'A' - 1);
            exit(0);
        }
        else 
            return;
    }
    for(int i = 1; i <= 2; ++i)
    {
        rel[0][xpos[x]] = 3 - i;
        rel[1][xpos[x]] = 3;
        s[xpos[x]] = 'a' + i - 1;
        dfs(x+1);
    }
}

int main()
{
    read(n);read(d);
    scanf("%s", s+1);
    d = 0;
    for(int i = 1; i <= n; ++i)
    {
        if(s[i] == 'x')
            xpos[++d] = i;
        else if(s[i] == 'a')
        {
            rel[0][i] = 2;
            rel[1][i] = 3;
        }
        else if(s[i] == 'b')
        {
            rel[0][i] = 1;
            rel[1][i] = 3;
        }
        else
        {
            rel[0][i] = 1;
            rel[1][i] = 2;
        }
    }
    read(m);
    for(int i = 1; i <= m; ++i)
    {
        char ch[4];
        read(req[i].a);
        scanf("%s", ch);
        req[i].ca = ch[0] - 'A' + 'a';
        read(req[i].b);
        scanf("%s", ch);
        req[i].cb = ch[0] - 'A' + 'a';
    }
    dfs(1);
    printf("-1");
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/Joker-Yza/p/11318789.html