ZOJ 3316 Game (带花树算法)
2013-08-21 18:16
246 查看
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3726
将同在L范围内的棋子建立边,然后做一般图的最大匹配(带花树算法),如果是完美匹配则输出YES;否则输出NO。
如果有完美匹配的话,顺着匹配拿掉棋子即可使后手赢。
View Code
将同在L范围内的棋子建立边,然后做一般图的最大匹配(带花树算法),如果是完美匹配则输出YES;否则输出NO。
如果有完美匹配的话,顺着匹配拿掉棋子即可使后手赢。
//#pragma comment(linker, "/STACK:102400000,102400000") #include<cstdio> #include<iostream> #include<cstring> #include<string> #include<cmath> #include<set> #include<list> #include<map> #include<iterator> #include<cstdlib> #include<vector> #include<queue> #include<stack> #include<algorithm> #include<functional> using namespace std; typedef long long LL; #define ROUND(x) round(x) #define FLOOR(x) floor(x) #define CEIL(x) ceil(x) const int maxn=500; const int inf=0x3f3f3f3f; const LL inf64=0x3f3f3f3f3f3f3f3fLL; const double INF=1e30; const double eps=1e-6; /** *一般图的最大基数匹配:带花树算法 *输入:g[][],n(输入从0到n-1,用addEdge()加边) *输出:gao()(最大匹配数),match[](匹配) */ //const int maxn=0; struct Matching { deque<int> Q; int n; //g[i][j]存放关系图:i,j是否有边,match[i]存放i所匹配的点 bool g[maxn][maxn],inque[maxn],inblossom[maxn],inpath[maxn]; int match[maxn],pre[maxn],base[maxn]; //找公共祖先 int findancestor(int u,int v) { memset(inpath,0,sizeof(inpath)); while(1) { u=base[u]; inpath[u]=true; if(match[u]==-1)break; u=pre[match[u]]; } while(1) { v=base[v]; if(inpath[v])return v; v=pre[match[v]]; } } //压缩花 void reset(int u,int anc) { while(u!=anc) { int v=match[u]; inblossom[base[u]]=1; inblossom[base[v]]=1; v=pre[v]; if(base[v]!=anc)pre[v]=match[u]; u=v; } } void contract(int u,int v,int n) { int anc=findancestor(u,v); //SET(inblossom,0); memset(inblossom,0,sizeof(inblossom)); reset(u,anc); reset(v,anc); if(base[u]!=anc)pre[u]=v; if(base[v]!=anc)pre[v]=u; for(int i=1; i<=n; i++) if(inblossom[base[i]]) { base[i]=anc; if(!inque[i]) { Q.push_back(i); inque[i]=1; } } } bool dfs(int S,int n) { for(int i=0; i<=n; i++)pre[i]=-1,inque[i]=0,base[i]=i; Q.clear(); Q.push_back(S); inque[S]=1; while(!Q.empty()) { int u=Q.front(); Q.pop_front(); for(int v=1; v<=n; v++) { if(g[u][v]&&base[v]!=base[u]&&match[u]!=v) { if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n); else if(pre[v]==-1) { pre[v]=u; if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1; else { u=v; while(u!=-1) { v=pre[u]; int w=match[v]; match[u]=v; match[v]=u; u=w; } return true; } } } } } return false; } void init(int n) { this->n = n; memset(match,-1,sizeof(match)); memset(g,0,sizeof(g)); } void addEdge(int a, int b) { ++a; ++b; g[a][b] = g[b][a] = 1; } int gao() { int ans = 0; for (int i = 1; i <= n; ++i) if (match[i] == -1 && dfs(i, n)) ++ans; return ans; } } match; int n,m,L; vector<pair<int,int> > node; int dist(pair<int,int> A,pair<int,int> B) { return abs(A.first-B.first)+abs(A.second-B.second); } void init() { node.clear(); match.init(m); } void input() { n=m; int u,v; while(m--) { scanf("%d%d",&u,&v); node.push_back(pair<int,int>(u,v)); } scanf("%d",&L); pair<int,int> x,y; for(int i=0;i<node.size();i++) { x=node[i]; for(int j=0;j<node.size();j++) { if(i==j) continue; y=node[j]; if(dist(x,y)<=L) match.addEdge(i,j); } } } void solve() { if(match.gao()*2==n) puts("YES"); else puts("NO"); } int main() { // std::ios_base::sync_with_stdio(false); // freopen("in.cpp","r",stdin); while(~scanf("%d",&m)) { init(); input(); solve(); } return 0; }
View Code
相关文章推荐
- ZOJ 3316 Game 一般图最大匹配带花树
- zoj 3316 Game (一般图匹配带花树)
- zoj 3316 Game(带花树+完美匹配)
- ZOJ 3316 Game 一般图最大匹配带花树
- ZOJ 3316 Game 一般图匹配
- 带花树(一般图最大匹配)详解 ZOJ 3316
- zoj 3316 Game 一般图最大匹配+博弈 有N个棋子在棋盘上,2个人轮流拿走一个棋子,第一步可以拿任意一个,而之后每一步必须拿上一步拿走的棋子曼哈顿长度L以内的棋子,问,后手是否能赢
- [Game] 游戏开发中的数学和物理算法:角度 vs 弧度
- (算法)Game
- zoj 3791 An Easy Game
- ZOJ 2593 One Person Game(扩展欧几里德、|x| + |y|最小)
- ZOJ 3646 (匹配匈牙利..算法)
- ZOJ 3593 One Person Game
- ZOJ 3329 — One Person Game
- ZOJ1016 题解此题一开始想用模拟算法结果调试了很久也没做出来,之后在网上看到这种方法很巧妙,果断采用。
- 带花树算法浅谈&&bzoj4405: [wc2016]挑战NPC
- Zoj 3529 A Game Between Alice and Bob 数论+博弈Nim 快速求数中有多少个素数因子
- ZOJ 3593 One Person Game
- ZOJ 3529 - A Game Between Alice and Bob(素因子+博弈)
- ZOJ 3329 One Person Game(概率dp求期望)