LibreOJ #6043.「雅礼集训 2017 Day7」蛐蛐国的修墙方案 搜索

题意

给一个长度为n的排列,要求构造一个长度为n的合法括号序,要求满足,构造一张n个点的图,当且仅当第i个位置是左括号时,点i向点p[i]连边,最后形成的图必须满足每个点的度数均为一。
n100 n ≤ 100

分析

我们在每一个i和p[i]之间连一条双向变,不难发现一条边的两个端点必然恰好有一个是左括号。
是不是看上去就像一道noip普及组naive千里送温暖做好事不求回报easy弱智sb无聊简直不能再水的超级裸题,只要对每个连通分量搜索一下就能过了。
注意适当加剪枝,比如说大小为2的可以直接贪心还有先搜较大的连通块之类的。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

const int N=105;

int n,cnt,last[N],ans[N],a[N][N],tot,rk[N];
bool vis[N];
struct edge{int to,next;}e[N*2];

void addedge(int u,int v)
{
    e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;
    e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;
}

void pre(int x)
{
    vis[x]=1;a[tot][++a[tot][0]]=x;
    for (int i=last[x];i;i=e[i].next)
        if (!vis[e[i].to]) pre(e[i].to);
}

bool dfs(int x)
{
    if (x>tot) return 1;
    int y=rk[x];
    for (int i=1;i<=a[y][0];i++) ans[a[y][i]]=i&1;
    int s=0;
    for (int i=1;i<=n;i++)
    {
        s+=!ans[i]?1:-1;
        if (s<0) break;
    }
    if (s>=0&&dfs(x+1)) return 1;
    for (int i=1;i<=a[y][0];i++) ans[a[y][i]]=(i&1)^1;
    s=0;
    for (int i=1;i<=n;i++)
    {
        s+=!ans[i]?1:-1;
        if (s<0) break;
    }
    if (s>=0&&dfs(x+1)) return 1;
    for (int i=1;i<=a[y][0];i++) ans[a[y][i]]=0;
    return 0;
}

bool cmp(int x,int y)
{
    return a[x][0]<a[y][0];
}

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        addedge(x,i);
    }
    for (int i=1;i<=n;i++)
        if (!vis[i])
        {
            tot++;a[tot][0]=0;pre(i);
            if (a[tot][0]==2) ans[std::max(a[tot][1],a[tot][2])]=1,tot--;
        }
    for (int i=1;i<=tot;i++) rk[i]=i;
    std::sort(rk+1,rk+tot+1,cmp);
    dfs(1);
    for (int i=1;i<=n;i++) putchar(!ans[i]?'(':')');
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值