• LOJ


    ( ext{Description})

    传送门

    ( ext{Solution})

    题目有一个限制:(P_i) 是个排列。

    那么显然有:每个点只有一个点连向自己,只有一个点被自己连向。

    是不是听起来很熟悉?这就是多个简单环组成的图(环大小可以为 (1))。

    不过根据题目,发现出现奇环一定是无解的。因为要满足题目要求就必须在环上取一条边,这条边相邻的两条边都不能取,所以奇环是无解的。

    只考虑偶环。对于每个偶环,显然就只有两种状态(环上相邻边取或不取序列):({0,1,0,1},{1,0,1,0})

    不过这样是 (mathcal O(2^{frac{n}{2}})) 的,直接 ( ext T) 飞。

    不过我们发现长度为 (2) 的偶环是可以特判的!设这个偶环两点为 (i,j),且 (i<j),我们就令 (i) 为左括号,(j) 为右括号。因为这样不会增多未匹配的个数,反之就有可能。

    你可能会觉得会不会有这种情况(好吧就是我觉得):(j=i+1),在 (i) 前正好有左括号,如果令 (i) 为右括号就将出现 (()(),反之为 ((())。你会发现如果第一种情况能构造出解右边就有右括号与 (j) 的左括号匹配,那么显然可以和前面的左括号匹配。

    时间复杂度 (mathcal O(2^{frac{n}{4}}))

    ( ext{Code})

    #include <cstdio>
    
    #define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
    #define fep(i,_l,_r) for(register signed i=(_l),_end=(_r);i>=_end;--i)
    #define print(x,y) write(x),putchar(y)
    
    template <class T> inline T read(const T sample) {
        T x=0; int f=1; char s;
        while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
        while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
        return x*f;
    }
    template <class T> inline void write(const T x) {
        if(x<0) return (void) (putchar('-'),write(-x));
        if(x>9) write(x/10);
        putchar(x%10^48);
    }
    
    #include <vector>
    #include <cstdlib>
    using namespace std;
    
    const int maxn=105;
    
    vector <int> g[maxn];
    int n,p[maxn],cnt,siz[maxn];
    bool vis[maxn],co[maxn];
    
    void FindCircle(int u,int id) {
    	if(vis[u]) return;
    	g[id].push_back(u); vis[u]=1; ++siz[id];
    	FindCircle(p[u],id);
    }
    
    void ok() {
    	int tot=0;
    	rep(i,1,n) {
    		tot+=(co[i]?-1:1);
    		if(tot<0) return;
    	}
    	rep(i,1,n) putchar(co[i]?')':'('); puts("");
    	exit(0);
    }
    
    void dfs(int x) {
    	if(x>cnt) return ok();
    	if(siz[x]==2) {
    		co[g[x][0]]=0,co[g[x][1]]=1;
    		dfs(x+1);
    		return;
    	} 
    	rep(i,0,g[x].size()-1) co[g[x][i]]=(i&1); dfs(x+1);
    	rep(i,0,g[x].size()-1) co[g[x][i]]=(!(i&1)); dfs(x+1);
    }
    
    int main() {
    	n=read(9);
    	rep(i,1,n) p[i]=read(9);
    	rep(i,1,n)
    		if(!vis[i]) FindCircle(i,++cnt);
    	dfs(1);
    	return 0;
    }
    
  • 相关阅读:
    由于可能不会将凭据发送到远程计算机,因此将不会进行连接。若要获得协助,请与您的系统管理员联系。
    URL编码与解码
    linux服务器openjdk11环境easypoi导出excel报错(class sun.font.CompositeFont cannot be cast to class sun.font.PhysicalFont)
    解决Drools中文乱码
    CISSP-什么是安全冠军以及您为什么需要安全冠军
    windows环境中JDK环境变量配置
    【Django】定时任务
    【Django】权限之has_perm
    一些连接
    数据库
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/14073060.html
Copyright © 2020-2023  润新知