zoukankan      html  css  js  c++  java
  • loj6043 「雅礼集训 2017 Day7」蛐蛐国的修墙方案

    传送门:https://loj.ac/problem/6043

    【题解】

    我们考虑这是个置换,所以一定形成了很多不相交的环。

    对于每个环,我们只能选一段、不选、选一段、不选这样交替下去。

    显然只有偶环是有解的,所以只考虑偶环。

    每个偶环有2种方案(第一个选,第一个不选),直接枚举是O(2^(n/2))的,复杂度接受不了。

    我们发现,2元环的左括号一定放在前面更优(更容易形成括号序列),所以贪心放,剩下的最小是4元环,枚举即可,所以复杂度是O(2^(n/4))。

    写个dfs然后发现常数太大。。。(还是过了)

    # include <vector>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 200 + 10;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, p[M], ans[M];
    int h[M][M], hn[M], a[M], an;
    int m; 
    
    int head[M], nxt[M], to[M], tot = 0;
    inline void add(int u, int v) {
        ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
    }
    inline void adde(int u, int v) {
        add(u, v), add(v, u);
    }
    
    bool vis[M]; 
    inline void dfs(int x, int fa) {
        if(vis[x]) return ; 
        vis[x] = 1; 
        a[++an] = x;
        for (int i=head[x]; i; i=nxt[i]) 
            if(to[i] != fa) dfs(to[i], x); 
    }
    
    inline void solve(int x) {
        an = 0;
        dfs(x, 0);
        if(an == 2) {
            if(a[1] < a[2]) ans[a[1]] = 1;
            else ans[a[2]] = 1;
        } else {
            ++m; hn[m] = an; 
            for (int i=1; i<=an; ++i) h[m][i] = a[i];
        }
    }
    
    inline bool chk() {
        int sum = 0;
        for (int i=1; i<=n; ++i) {
            sum = sum + (ans[i] ? 1 : -1);
            if(sum < 0) return false;
        }
        for (int i=1; i<=n; ++i) putchar(ans[i] ? '(' : ')'); 
        puts("");
        return true;
    }
    
    bool ok;
    inline void gans(int x) {
        if(ok) return ; 
        if(x == m + 1) {
            if (chk()) ok = 1;
            return ;
        }
        for (int i=1; i<=hn[x]; ++i) ans[h[x][i]] = (i&1);
        gans(x+1);
        for (int i=1; i<=hn[x]; ++i) ans[h[x][i]] ^= 1;
        gans(x+1);
    }
    
    int main() {
        freopen("c.in", "r", stdin);
        freopen("c.out", "w", stdout); 
        cin >> n;
        for (int i=1; i<=n; ++i) scanf("%d", &p[i]); 
        for (int i=1; i<=n; ++i) adde(i, p[i]);
        for (int i=1; i<=n; ++i) if(!vis[i]) solve(i); 
    //    for (int i=1; i<=m; ++i, puts("
    "))
    //        for (int j=1; j<=hn[i]; ++j)
    //            printf("%d ", h[i][j]); 
        gans(1); 
        return 0;
    }
    View Code
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    关于模态/非模态对话框不响应菜单的UPDATE_COMMAND_UI消息(对对WM_INITMENUPOPUP消息的处理)
  • 原文地址:https://www.cnblogs.com/galaxies/p/loj6043.html
Copyright © 2011-2022 走看看