【ZOJ3316】Game(带花树)
2018-04-04 22:34
218 查看
【ZOJ3316】Game(带花树)
题面
Vjudge翻译:
给定棋盘上\(n\)个旗子
一开始先手可以随便拿,
然后每次都不能取离上次的曼哈顿距离超过\(L\)的旗子
谁不能动谁输。
问后手能否赢?
题解
假的博弈论对于所有曼哈顿距离小于等于\(L\)的点连边
检查是否存在完美匹配
如果存在完美匹配,每次先手选择一个点,后手只需要选择对应的点即可。
否则一定存在一个无法匹配的点,与它曼哈顿距离小于等于\(L\)的个数一定是偶数个(如果是奇数个就会与它匹配)
那么这个联通块的大小是奇数个,后手必败。(假的证明)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define ll long long #define RG register #define MAX 362 inline int read() { RG int x=0,t=1;RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } struct Line{int v,next;}e[MAX*MAX]; int h[MAX],cnt=1; inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;} int dfn[MAX],tim; int f[MAX],n; int pre[MAX],vis[MAX],match[MAX]; int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);} int lca(int u,int v) { ++tim;u=getf(u),v=getf(v); while(dfn[u]!=tim) { dfn[u]=tim; u=getf(pre[match[u]]); if(v)swap(u,v); } return u; } queue<int> Q; void blossom(int x,int y,int w) { while(getf(x)!=w) { pre[x]=y;y=match[x]; if(vis[y]==2)vis[y]=1,Q.push(y); if(f[x]==x)f[x]=w; if(f[y]==y)f[y]=w; x=pre[y]; } } bool Aug(int S) { for(int i=1;i<=n;++i)f[i]=i,vis[i]=pre[i]=0; while(!Q.empty())Q.pop();Q.push(S);vis[S]=1; while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=h[u];i;i=e[i].next) { int v=e[i].v; if(getf(u)==getf(v)||vis[v]==2)continue; if(!vis[v]) { vis[v]=2;pre[v]=u; if(!match[v]) { for(int x=v,lst;x;x=lst) lst=match[pre[x]],match[x]=pre[x],match[pre[x]]=x; return true; } vis[match[v]]=1;Q.push(match[v]); } else { int w=lca(u,v); blossom(u,v,w);blossom(v,u,w); } } } return false; } void init() { memset(h,0,sizeof(h));cnt=1; memset(match,0,sizeof(match)); } int X[MAX],Y[MAX],L; int main() { while(scanf("%d",&n)!=EOF) { init(); for(int i=1;i<=n;++i)X[i]=read(),Y[i]=read(); L=read();int ans=0; if(n&1){puts("NO");continue;} for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j) if(abs(X[i]-X[j])+abs(Y[i]-Y[j])<=L) Add(i,j),Add(j,i); for(int i=1;i<=n;++i)if(!match[i])ans+=Aug(i); (ans==n/2)?puts("YES"):puts("NO"); } return 0; }
相关文章推荐
- zoj3316 Game,一般图匹配,带花树
- zoj 3316 Game (一般图匹配带花树)
- ZOJ 3316 Game (带花树算法)
- zoj3316【一般图最大匹配 带花树开花】
- [ZOJ3316]Game
- ZOJ 3316 Game 一般图最大匹配带花树
- [ZOJ3316]Game
- ZOJ 3316 Game 一般图最大匹配带花树
- zoj 3316 Game(带花树+完美匹配)
- ZOJ3316:Game
- [ZOJ3316]:Game
- 《The Accounting Game》读书笔记
- Codeforces Round #426 (Div. 2)-C. The Meaningless Game
- hdu 5975 Aninteresting game Time Limit: 2000/1000 MS (Java/Others) Memory LimiAninteresting game
- Jump Game II
- Codeforces Round #426 (Div. 2) B.The Festive Evening+C.The Meaningless Game
- 热身题B——B - Candy Sharing Game
- Codefores Round #263 (div2) B. Appleman and Card Game
- 好题-Round #426 (Div. 2)C-二分&&思维||质因数分解-The Meaningless Game
- python实现生命游戏的示例代码(Game of Life)