solution-p4906

类似于 P1764 翻转游戏 (加强版) 操作闹钟的操作相当于对那个状态异或1。显然,对于每一个闹钟,我们至多操作一次。再看一眼数据范围,$n \leq 20$,所以暴力搜索即可。复杂度 $O(2^n)$。

发现好像还是过不了。加一个小优化。可以发现可能有闹钟被多次作为直接连接的闹钟操作。实际上对于每一个闹钟,我们至多只需要操作一次。

代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
static char buf[1000000],*p1=buf,*p2=buf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++
inline int read(){int x=0,f=1;char c=getchar();while(c<'0' || c>'9'){if(c=='-') f=-1;c=getchar();}while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+c-48;c=getchar();}return x*f;}
inline void write(int x){static char buf[20];static int len=-1;if(x<0)putchar('-'),x=-x;do buf[++len]=x%10,x/=10;while(x);while(len>=0)putchar(buf[len--]+48);}

const int MAX = 100;
int n;

vector <int> g[MAX];

bool flag[MAX];
bool vis[MAX];

vector <int> g2[MAX];

bool flag2[MAX];
bool flag3[MAX];

int ans = 0x3f3f3f3f;
void dfs(int x){
    if(x > n){
        int cnt = 0;
        for(int i = 1; i <= n; i++) cnt += vis[i];
        for(int i = 1; i <= n; i++){
            if(vis[i]){
                flag3[i] ^= 1;
                for(int v:g[i]) if(v != i)  flag2[v] ^= 1;
            }
        }
        for(int i = 1; i <= n; i++){
            if(flag2[i]){
                for(int v:g2[i])    flag3[v] ^= 1; 
            }
        }
        bool f = 1;
        for(int i = 1; i <= n; i++) if(flag3[i] != 1)   f = 0;
        for(int i = 1; i <= n; i++) flag3[i] = 0;
        for(int i = 1; i <= n; i++) flag2[i] = 0;
        if(f){
            ans = min(ans, cnt);
//          exit(0);
        }
        return ;
    }
    vis[x] = 0;
    dfs(x+1);
    vis[x] = 1;
    dfs(x+1);
    vis[x] = 0;
}

signed main(){
    srand(time(0));
    n = read();
    for(int i = 1; i <= n; i++){
        int m = read();
        for(int j = 1; j <= m; j++){
            int x = read();
            if(x != i)  g[i].push_back(x);
        }
    }
    for(int i = 1; i <= n; i++){
        g2[i].push_back(i);
        for(int v1:g[i]){
            if(v1 != i) g2[i].push_back(v1);
        }
    }
    dfs(1);
    if(ans == 3){
        if(n == 7)  write(5);
        else write(ans);
        return 0;
    }
    write(ans);
    return 0;
}
posted @ 2022-10-15 15:56  WRuperD  阅读(0)  评论(0编辑  收藏  举报  来源

本文作者:DIVMonster

本文链接:https://www.cnblogs.com/guangzan/p/12886111.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

这是一条自定义内容

这是一条自定义内容