• 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面试题及答案整理(持续更新)
    CentOS6.4-mini系统服务列表
    Linux内核编译,模块尺寸变大的解决办法
    Configuration Opennebula3.8 & 4.x Virtual Machines Contextualizing
    CentOS6.3上Opennebula 3.8 VLAN配置
    Ubuntu 12.04 LTS主机名、IP、DNS配置总结
    Linux su
    Git安装配置总结
    Linux CentOS添加163yum源
    Linux 内核编译 modules ehci-hcd, ohci-hcd, uhci-hcd not found
  • 原文地址:https://www.cnblogs.com/galaxies/p/loj6043.html
Copyright © 2020-2023  润新知