P2962 [USACO09NOV]Lights G(Meet In The Middle)
[USACO09NOV]Lights G
题目描述
给出一张n个点n条边的无向图,每个点的初始状态都为0。
你可以操作任意一个点,操作结束后该点以及所有与该点相邻的点的状态都会改变,由0变成1或由1变成0。
你需要求出最少的操作次数,使得在所有操作完成之后所有n个点的状态都是1。
输入格式
第一行两个整数n, m
之后m行,每行两个整数a, b,表示在点a, b之间有一条边。
输出格式
一行一个整数,表示最少需要的操作次数。
样例
样例输入
5 6
1 2
1 3
4 2
3 4
2 5
5 3
样例输出
3
思路
使用Meet In The Middle,先将1~mid点的全部情况遍历,将可能得到的结果以及到达对应结果状态所需要的最少步数记录下来,由于1<<35过大,所以推荐使用map进行存储。
将前半部分遍历完成后遍历后半部分,对于每个操作可以得到一个最终状态,将最终状态与全1情况异或可以得到对应的互补状态,然后维护最小操作次数即可。
易错点
1.左移的时候记得使用1ll,不然会爆int。
2.需要初始化map[0] = 0,不然当后半能达到全1状态时会多加上几次操作(前半到达全0的次小操作次数)
#include<bits/stdc++.h>
using namespace std;
#define int long long
vector<int> edge[50];
int N, M, ans;
map<int, int> half;
bool option(int op, int n)
{
//查看是否对第n位进行操作
return (op >> n) & 1;
}
int answer(int a)
{
//得到互补状态
return ans ^ a;
}
bool getState(int op, int n)
{
/*
判断当前位在某种操作下最终状态是0还是1
*/
int res = 0;
if(option(op, n)){
res += 1;
}
for(int i = 0; i < edge[n].size(); i++){
if(option(op, edge[n][i])) res += 1;
}
return (res & 1)?true:false;
}
int getOptionTime(int op)
{
/*
获得一个操作的总操作次数
*/
int res = 0;
while(op){
res += (op & 1);
op >>= 1;
}
return res;
}
int setStateEnd(int op)
{
/*
获得一个操作对应的最终状态,返回对应二进制数
*/
int res = 0;
for(int i = 0; i < N; i++){
if(getState(op, i)){
res ^= (1ll << i);
}
}
return res;
}
/*void print(int a)
{
stack<int> s;
while(a){
s.push(a & 1);
a >>= 1;
}
while(s.size()){
cout << s.top();
s.pop();
}
cout <<endl;
}*/
signed main()
{
cin >> N >> M;
half[0] = 0;// 维护map[0] = 0
ans = (1ll << N) - 1;// ans对应的最终想要的状态,用于与得到的状态异或来获取另外的部分
int minTime = 0x3f3f3f3f;
for(int i = 0; i < M; i++){// 建边
int a, b;
cin >> a >> b;
edge[--a].push_back(--b);
edge[b].push_back(a);
}
int mid = N >> 1ll;
for(int op = 0; op <= (1ll << (N/2))-1; op++){// 枚举前半部分的全部操作情况
int res = setStateEnd(op);// 得到操作情况对应的结果状态
//维护最小操作次数
if(half.count(res)){
half[res] = min(half[res], getOptionTime(op));
}
else{
half[res] = getOptionTime(op);
}
}
for(int op = 0; op <= (1ll << N)-(1ll << (N/2)); op += (1ll << (N/2))){// 枚举后半部分的全部操作情况
int res = setStateEnd(op);
int thisAns = answer(res);// 判断当前状态的互补状态
if(half.count(thisAns)){// 查看是否存在互补状态,若存在,则维护最小值
int nowTime = half[thisAns];
nowTime += getOptionTime(op);
minTime = min(minTime, nowTime);
}
}
/*cout << "------" << endl;
print(setStateEnd((1ll << 33) + (1ll << 34)));
print(ans);
cout << "------" << endl;
for(int i = 0; i < N; i++){
cout << i << "---->";
for(int j = 0; j <edge[i].size(); j++){
cout << edge[i][j] << ' ';
}
cout << endl;
}*/
cout << minTime <<endl;
return 0;
}
P2962 [USACO09NOV]Lights G(Meet In The Middle)的更多相关文章
- luogu P2962 [USACO09NOV]灯Lights 高斯消元
目录 题目链接 题解 题目链接 luogu P2962 [USACO09NOV]灯Lights 题解 可以折半搜索 map合并 复杂度 2^(n / 2)*logn 高斯消元后得到每个点的翻转状态 爆 ...
- meet in the middle 折半搜索 刷题记录
复杂度分析 假设本来是n层,本来复杂度是O(2^n),如果meet in middle那就是n/2层,那复杂度变为O( 2^(n/2) ),跟原来的复杂度相比就相当于开了个方 比如如果n=40那爆搜2 ...
- [CSP-S模拟测试]:答题(meet in the middle)
题目传送门(内部题142) 输入格式 输入文件的第一行为两个数$n,P$. 接下来一行$n$为个正整数,表示每道题的分数. 输出格式 输出一行一个正整数,为至少需要获得的分数. 样例 样例输入: 2 ...
- Meet in the middle学习笔记
Meet in the middle(MITM) Tags:搜索 作业部落 评论地址 PPT中会讲的很详细 当搜索的各项互不影响(如共\(n\)个物品前\(n/2\)个物品选不选和后\(n/2\)个物 ...
- Meet in the middle
搜索是\(OI\)中一个十分基础也十分重要的部分,近年来搜索题目越来越少,逐渐淡出人们的视野.但一些对搜索的优化,例如\(A\)*,迭代加深依旧会不时出现.本文讨论另一种搜索--折半搜索\((meet ...
- SPOJ4580 ABCDEF(meet in the middle)
题意 题目链接 Sol 发现abcdef是互不相关的 那么meet in the middle一下.先算出abc的,再算def的 注意d = 0的时候不合法(害我wa了两发..) #include&l ...
- codevs1735 方程的解数(meet in the middle)
题意 题目链接 Sol 把前一半放在左边,后一半放在右边 meet in the middle一波 统计答案的时候开始想的是hash,然而MLE了两个点 实际上只要排序之后双指针扫一遍就行了 #inc ...
- 【BZOJ4800】[Ceoi2015]Ice Hockey World Championship (meet in the middle)
[BZOJ4800][Ceoi2015]Ice Hockey World Championship (meet in the middle) 题面 BZOJ 洛谷 题解 裸题吧,顺手写一下... #i ...
- 【CF888E】Maximum Subsequence(meet in the middle)
[CF888E]Maximum Subsequence(meet in the middle) 题面 CF 洛谷 题解 把所有数分一下,然后\(meet\ in\ the\ middle\)做就好了. ...
- 【CF912E】Prime Game(meet in the middle)
[CF912E]Prime Game(meet in the middle) 题面 CF 懒得翻译了. 题解 一眼题. \(meet\ in\ the\ middle\)分别爆算所有可行的两组质数,然 ...
随机推荐
- Linux下的zip和tar压缩解压缩命令详解
一.zip压缩工具 zip的压缩包在windows和linux中都比较常用,它可以压缩目录和文件,压缩时录时,需要指定目录下的文件.zip后面先跟目标文件名,即压缩后得自定义压缩包名,然后跟要压缩的文 ...
- IE 浏览器element-ui table: show-overflow-tooltip 临界值时失效
问题: 在使用el-table表格时,有时会用到show-overflow-tooltip属性,即当单元格内容不能完全显示时显示tooltip文字提示,并且单元格里的内容显示省略号. 但是在ie浏览器 ...
- MindManager离线安装包官网下载
软件官网:https://www.mindjet.com/ 注意:不建议在思杰马克丁及其相关合作网站下载该软件,更不建议在其旗下站点购买该软件授权. 目前来说,官网正常下载的话它会要求你填写一些信息, ...
- CCF 201803-4 棋局评估
一. 对抗搜索的适用范围 在博弈论题目中,如果决策双方的获胜条件是截然相反的,即一方要求得分越高越好,另一方要求得分越低越好,这时我们就可以用上对抗搜索算法. 二.对抗搜索的主要思想 对抗搜索的核心思 ...
- 新手:git回滚代码,合并代码解决冲突
回滚到某个tag: git reset --hard 70438034dc git push -f 合并---解决冲突---提交: Step 1. Fetch and check out the br ...
- 解决idea中按退格键(Backspace)回到上一行问题
开始学习java时,第一次用idea,该问题困扰一上午,网上也没有解决方案,最后自己摸索如下.打开File-> Settings->Editor->Smart Keys,将To pr ...
- kubectl工具安装指南
kubectl是一个用于连接Service Mesh控制平面的工具,可以安装在办公电脑的Windows系统上,也可以安装在虚拟机的Linux系统上,只要网络能与控制平面的公网地址互通即可.下面分别介绍 ...
- 在unity编辑器中,导出/保存文件,使用EditorUtility.SaveFilePanel,代替运行时的方法。
在项目中(运行时),已经有个功能是导出文件到本地磁盘,使用的方法是常见的DllImport("Comdlg32.dll")并进行封装.详情可参考:https://github.co ...
- 【Linux】Ubuntu随笔
Ubuntu声明环境变量时使用 export JAVA_HOME=/xx/xx/xx,当需要引用时要写成 $JAVA_HOME 所以配置环境变量并声明方法如下: vim ~/.bashrc expor ...
- c++学习1 基础关键词
一 "const" 修饰变量 只能被初始化和读取,不能被赋值更改,且必需初始化,不初始化的话会因为读取到随机数而报错. example: const int date=100; c ...