• 【题解】NOI2017游戏


    2-SAT。洛谷P3845

    一开始以为——怎么有3个呢?后来发现因为每个地图都有一种车是不能用的,所以就等于每一个地图都有两个适应的车啦。

    那么对于x类型的地图呢——只有8个,直接2^8暴力枚举每一种可能,就转化为了普通的问题。

    令u,u'分别为一个地图适应的两种车,那么对于一个要求h1 - d1, h2 - d2而言,如果第一个既不是u,也不是u’,说明可以无视;如果第二个都不能满足,

    就连d1 - d1',表示如果必须选第一辆,问题无解。其余情况则d1-d2,d2'-d1'(重要!保证图的对偶性)

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 500050
    int n, timer, dep[maxn], m, cnp = 1, d1[maxn], d2[maxn], c1[maxn], c2[maxn], cnt, a[maxn];
    int low[maxn], dfn[maxn], num[maxn]; 
    int sum;
    int head[maxn]; 
    bool flag = false, vis[maxn], mark[maxn];
    string s; 
    char tem1[3], tem2[3];
    stack <int> st;
    
    struct edge
    {
        int last, to;
    }E[maxn];
    
    void add(int u, int v)
    { 
        E[cnp].to = v, E[cnp].last = head[u]; head[u] = cnp ++;
    }
    
    int getid(int r, int col)
    {
        if(a[r] == col) return 0;
        else if(a[r] == 0) return 2 * r + col - 1;
        else if(a[r] == 1) return 2 * r + col / 2;
        else return 2 * r + col; 
    }
    
    void tarjan(int u)
    {
        dep[u] = dfn[u] = low[u] = ++ timer;
        vis[u] = mark[u] = true;
        st.push(u);
        for(int i = head[u]; i; i = E[i].last)
        {
            int v = E[i].to;
            if(vis[v])
            { if(mark[v] && low[u] > dfn[v]) low[u] = dfn[v]; }
            else 
            {
                tarjan(v);
                low[u] = min(low[v], low[u]);
            }
        }
        if(dfn[u] == low[u])
        {
            int j;
            ++ cnt;
            do
            {
                j = st.top();
                st.pop();
                num[j] = cnt;
                mark[j] = false;
            }while(!st.empty() && j != u);
        }
    }
    
    void init()
    {
        memset(head, 0, sizeof(head));
        memset(dep, 0, sizeof(dep));
        cnt = timer = 0, cnp = 1; 
        memset(vis, 0, sizeof(vis));
    }
    
    void solve()
    {
        init();
        for(int i = 1; i <= m; i ++)
        {
            int x = getid(d1[i], c1[i]), y = getid(d2[i], c2[i]);
            if(x)
            {
                if(y) add(x, y), add(y ^ 1, x ^ 1);
                else add(x, x ^ 1);
            }
        }
        for(int i = 2; i <= 2 * n + 1; i ++)
            if(!vis[i]) tarjan(i);
        for(int i = 1; i <= n; i ++) 
            if(num[i * 2] == num[i * 2 ^ 1]) return;
        flag = true;
        for(int i = 1; i <= n; i ++)
        {
            if(a[i] == 0) putchar(num[i * 2] < num[i * 2 ^ 1] ? 'B' : 'C');
            else if(a[i] == 1) putchar(num[i * 2] < num[i * 2 ^ 1] ? 'A' : 'C');
            else putchar(num[i * 2] < num[i * 2 ^ 1] ? 'A' : 'B');
        }
        return;
    }
    
    void dfs(int x)
    {
        if(flag) return;
        if(x > n) 
        {
            solve();
            return;
        }
        if(a[x] == -1) a[x] = 0, dfs(x + 1), a[x] = 1;
        dfs(x + 1);
    }
    
    int main()
    {
        string s;
        int d;
        cin >> n >> d;
        cin >> s;
        n = s.length();
        for(int i = 0; i < n; i ++)
        {
            if(s[i] == 'a') a[i + 1] = 0;
            else if(s[i] == 'b') a[i + 1] = 1;
            else if(s[i] == 'c') a[i + 1] = 2;
            else a[i + 1] = -1;
        }
        cin >> m;
        for(int i = 1; i <= m; i ++)
        {
            scanf("%d%s%d%s", &d1[i], tem1, &d2[i], tem2);
            c1[i] = tem1[0] - 'A', c2[i] = tem2[0] - 'A'; 
        } 
        dfs(1);
        if(!flag) printf("-1
    ");
        return 0;
    }
  • 相关阅读:
    WPF中的brushes
    com中的线程模式(转)
    线程同步
    WPF线程
    应用程序管理(Application)
    WPF的继承结构树
    HTML技巧100例(一)
    多个网站共用一个空间的超值玩法
    用JavaScript实现浏览器地震效果
    HTML技巧100例(二)
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/8445813.html
Copyright © 2020-2023  润新知