HDU 3267 Graph Game(博弈论+图论+暴力)
题意:
- 有一棵 \(n\) 个节点的图 \(G\),R 和 B 两个人轮流操作,R 先操作。
- 每次操作 R 可以染红任意一条未染色的边,B 可以染蓝任意一条未染色的边
- R 的目标是染成一棵全蓝的生成树,R 的目标是阻止后手染成一棵全蓝的生成树,问谁会赢。
- \(n \in [1,10]\),\(m \in [1,30]\)
yet another 博弈论 problem......
不难猜出本题的结论是如果 \(G\) 中存在两棵边集不相交的生成树,答案为 \(\texttt{YES}\),否则答案为 \(\texttt{NO}\),你手玩几组数据应该就可以看出来。
但是怎么证明呢?
对于游戏中任意一个局面,我们分以下几种情况考虑:
- 如果 \(G\) 中存在两棵生成树 \(T_1,T_2\),满足 \(T_1,T_2\) 只由蓝边或无色边组成,并且 \(T_1,T_2\) 中无色边组成的边集不相交。
如果 R 染红的边不在 \(T_1,T_2\) 中,那么 B 随便染蓝一条边都可以保持这个局面。因为你染蓝这条边后 \(T_1,T_2\) 依然满足上述条件。
如果 R 染红的边在 \(T_1,T_2\) 中,不妨假设 R 染红的边为 \(e_1 \in T_1\),那么 B 必然可以找出 \(e_2 \in T_2\),满足从 \(T_1\) 中删除 \(e_1\) 加入 \(e_2\) 依然是一个生成树 \(T'_1\)。你感性理解一下,去掉 \(e_1\) 之后原树 \(T_1\) 分成两个点集 \(V_1,V_2\),由于 \(T_2\) 是一棵树,那么必然有一条边 \(e_2\) 沟通了 \(V_1,V_2\),不然 \(T_2\) 就不连通了。如果此时 \(e_2\) 未染色,那么 B 可以将 \(e_2\) 染成蓝色,此时 \(T'_1\) 与 \(T_2\) 依然满足上述条件。如果 \(e_2\) 已经染成蓝色,那么 B 随便染蓝一条边也不会使局面更坏。
综上,这种情况下 B 有必胜策略。 - 如果 \(G\) 中不存在两棵生成树 \(T_1,T_2\),满足 \(T_1,T_2\) 只由蓝边或无色边组成,并且 \(T_1,T_2\) 中无色边组成的边集不相交。
Ⅰ. 如果 \(G\) 中存在一条边 \(e\) 满足 B 将 \(e\) 染蓝后会得到 1 的局面。那么 R 可将 \(e\) 染红。此时,先手边后手,后手变先手,根据 1 的结论,R 可以染出一棵全红的生成树,B 就染不出一棵全蓝的生成树了。
Ⅱ. 如果 \(G\) 中不存在一条边 \(e\) 满足 B 将 \(e\) 染蓝后会得到 1 的局面。那么 R 可以随便染红一条边,因为 B 不管染蓝哪条边都得不到 1 的局面。
综上,这种情况下 R 有必胜策略。
接下来就是实现的问题。本题数据范围很小,而博主又太菜不会什么 Minmax 搜索之类的高级算法。只好采用暴搜的方法,暴力枚举一棵生成树的边集判断其他边是否能构成一棵生成树,由于 \(C_{30}^9=14307150\) 只达到 \(10^7\) 级别。因此你稍微剪点枝就可以过了。
/*
Contest: -
Problem: HDU 3267
Author: tzc_wk
Time: 2020.7.27
*/
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define all(a) a.begin(),a.end()
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,0x3f,sizeof(a))
#define fillsmall(a) memset(a,0xcf,sizeof(a))
#define y1 y1010101010101
#define y0 y0101010101010
typedef pair<int,int> pii;
inline int read(){
int x=0,neg=1;char c=getchar();
while(!isdigit(c)){
if(c=='-') neg=-1;
c=getchar();
}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
return x*neg;
}
bool ans=0;
int n,k,m,u[75],v[75],f[75],num=0;
bool vis[75];
inline int find(int x){
return (f[x]==x)?(x):find(f[x]);
}
int to[75],ecnt=0,nxt[75],hd[75];
inline void ae(int x,int y){
to[++ecnt]=y;
nxt[ecnt]=hd[x];
hd[x]=ecnt;
}
int used[75];
inline void findcomp(int x){
if(used[x]) return;
used[x]=1;
for(int i=hd[x];i;i=nxt[i]) findcomp(to[i]);
}
inline void dfs(int x,int lst){
if(x==n){
// num++;
// if(num%100000==0) cout<<num<<endl;
// fz(i,1,m) if(vis[i]) cout<<i<<" ";puts("");
fill0(hd);fill0(nxt);fill0(to);ecnt=0;fill0(used);
fz(i,1,m) if(!vis[i]) ae(u[i],v[i]),ae(v[i],u[i]);
findcomp(1);bool flg=1;
fz(i,1,n) if(!used[i]) flg=0;
if(flg) ans=1;
return;
}
for(int i=lst+1;i<=m;i++){
int _u=u[i],_v=v[i];
// if(rand()&1) swap(_u,_v);
int fu=find(_u),fv=find(_v);
if(fu!=fv){
f[fu]=fv;vis[i]=1;dfs(x+1,i);
if(ans) return;
vis[i]=0;f[fu]=fu;f[fv]=fv;
}
}
}
inline void solve(){
m=0;fill0(u);fill0(v);fill0(f);
fz(i,1,k){
int _u=read(),_v=read();_u++;_v++;
if(_u!=_v) u[++m]=_u,v[m]=_v;
}
fz(i,1,n) f[i]=i;
fill0(vis);ans=0;dfs(1,0);
if(ans) puts("YES");
else puts("NO");
}
signed main(){
while(scanf("%d %d",&n,&k)){
if(!~n) break;
solve();
}
return 0;
}
HDU 3267 Graph Game(博弈论+图论+暴力)的更多相关文章
- HDU 1557 权利指数 国家压缩 暴力
HDU 1557 权利指数 状态压缩 暴力 ACM 题目地址:HDU 1557 权利指数 题意: 中文题,不解释. 分析: 枚举全部集合,计算集合中的和,推断集合里面的团体是否为关键团队. 代码: ...
- [la P5031&hdu P3726] Graph and Queries
[la P5031&hdu P3726] Graph and Queries Time Limit: 10000/5000 MS (Java/Others) Memory Limit: ...
- HDU 1524 树上无环博弈 暴力SG
一个拓扑结构的图,给定n个棋的位置,每次可以沿边走,不能操作者输. 已经给出了拓扑图了,对于每个棋子找一遍SG最后SG和就行了. /** @Date : 2017-10-13 20:08:45 * @ ...
- HDU.2149 Public Sale (博弈论 巴什博弈)
HDU.2149 Public Sale (博弈论 巴什博弈) 题意分析 巴什博奕裸题 博弈论快速入门 代码总览 #include <bits/stdc++.h> using namesp ...
- HDU.1846 Brave Game (博弈论 巴什博弈)
HDU.1846 Brave Game (博弈论 巴什博弈) 题意分析 巴什博奕裸题 博弈论快速入门 代码总览 include <bits/stdc++.h> using namespac ...
- HDU 3726 Graph and Queries treap树
题目来源:HDU 3726 Graph and Queries 题意:见白书 思路:刚学treap 參考白皮书 #include <cstdio> #include <cstring ...
- 图论/暴力 Codeforces Beta Round #94 (Div. 2 Only) B. Students and Shoelaces
题目传送门 /* 图论/暴力:这是个连通的问题,每一次把所有度数为1的砍掉,把连接的点再砍掉,总之很神奇,不懂:) */ #include <cstdio> #include <cs ...
- HDU 3131 One…Two…Five! (暴力搜索)
题目链接:pid=3131">HDU 3131 One-Two-Five! (暴力搜索) 题意:给出一串数字,要求用加,减,乘,除(5/2=2)连接(计算无优先级:5+3*6=8*6= ...
- HDU 4467 Graph(图论+暴力)(2012 Asia Chengdu Regional Contest)
Description P. T. Tigris is a student currently studying graph theory. One day, when he was studying ...
随机推荐
- HCNP Routing&Switching之BGP路由宣告
前文我们了解了BGP报文结构.类型以及邻居状态相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15422924.html:今天我们来聊一聊BGP路由宣告 ...
- AIApe问答机器人Scrum Meeting 5.1
Scrum Meeting 5 日期:2021年5月1日 会议主要内容概述:汇报两日工作. 一.进度情况 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 李明昕 后端 Task ...
- AIApe问答机器人Scrum Meeting 5.5&5.6
Scrum Meeting 7 日期:2021年5月5日&2021年5月6日 会议主要内容概述:汇报近日工作,确定下一步计划,放弃"关键词提取"和"改进关键词&q ...
- QEvent
QEvent类是所有事件类的基类,每一个对象都包含事件参数.Qt的主事件循环(QCoreApplication::exec())从事件队列中接收本地窗口系统的事件,并将它们翻译成QEvent,将这些事 ...
- 深入理解xLua基于IL代码注入的热更新原理
目前大部分手游都会采用热更新来解决应用商店审核周期长,无法满足快节奏迭代的问题.另外热更新能够有效降低版本升级所需的资源大小,节省玩家的时间和流量,这也使其成为移动游戏的主流更新方式之一. 热更新可以 ...
- 21.6.25 test
\(NOI\) 模拟赛 \(T1\) 是树+位运算+dp+优化 打了 \(O(n^2)\) 的暴力dp,只拿到了35分,算了一下参赛的,人均65,中位数60.也能看出一些问题,对于一些模糊的猜测应该尝 ...
- 在Ubuntu下安装Solr
使用wget命令去官网下载solr的压缩包. 1 wget https://mirrors.bfsu.edu.cn/apache/lucene/solr/8.6.3/solr-8.6.3.tgz 使用 ...
- 如何优雅的处理 accept 出现 EMFILE 的问题
通常情况下,服务端调用 accept 函数会返回一个新的文件描述符,用于和客户端之间的数据传输 在服务器的开发中,有时会遇到这种情况:当调用 accept 函数接受客户端连接,函数返回失败,对应的错误 ...
- 好的编程习惯是减少bug最有效的方法
公司来了几个新手,有时候很简单的一个功能模块都要耗费好几天时间,总是在一些不相关的问题上死耗一整天,搞出莫名其妙的问题,找不到具体原因,总是怀疑编译出问题了,系统出问题了,板子出问题了,搞到快下班了叫 ...
- vue打包后反编译到源代码(reverse-sourcemap)
因为突然的疫情把我困在家了,家里的电脑没有源代码,但是需求还要改,工作还得继续... 从服务器下载了之前上传的打包后的文件,找了一圈反编译方法,得救了,在此记录一下. 1.npm install -- ...