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;
}