ZOJ 3316 Game (带花树算法)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3726

将同在L范围内的棋子建立边,然后做一般图的最大匹配(带花树算法),如果是完美匹配则输出YES;否则输出NO。

如果有完美匹配的话,顺着匹配拿掉棋子即可使后手赢。

  1 //#pragma comment(linker, "/STACK:102400000,102400000")
  2 #include<cstdio>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<string>
  6 #include<cmath>
  7 #include<set>
  8 #include<list>
  9 #include<map>
 10 #include<iterator>
 11 #include<cstdlib>
 12 #include<vector>
 13 #include<queue>
 14 #include<stack>
 15 #include<algorithm>
 16 #include<functional>
 17 using namespace std;
 18 typedef long long LL;
 19 #define ROUND(x) round(x)
 20 #define FLOOR(x) floor(x)
 21 #define CEIL(x) ceil(x)
 22 const int maxn=500;
 23 const int inf=0x3f3f3f3f;
 24 const LL inf64=0x3f3f3f3f3f3f3f3fLL;
 25 const double INF=1e30;
 26 const double eps=1e-6;
 27 
 28 /**
 29 *一般图的最大基数匹配:带花树算法
 30 *输入:g[][],n(输入从0到n-1,用addEdge()加边)
 31 *输出:gao()(最大匹配数),match[](匹配)
 32 */
 33 //const int maxn=0;
 34 struct Matching
 35 {
 36     deque<int> Q;
 37     int n;
 38     //g[i][j]存放关系图:i,j是否有边,match[i]存放i所匹配的点
 39     bool g[maxn][maxn],inque[maxn],inblossom[maxn],inpath[maxn];
 40     int match[maxn],pre[maxn],base[maxn];
 41 
 42     //找公共祖先
 43     int findancestor(int u,int v)
 44     {
 45         memset(inpath,0,sizeof(inpath));
 46         while(1)
 47         {
 48             u=base[u];
 49             inpath[u]=true;
 50             if(match[u]==-1)break;
 51             u=pre[match[u]];
 52         }
 53         while(1)
 54         {
 55             v=base[v];
 56             if(inpath[v])return v;
 57             v=pre[match[v]];
 58         }
 59     }
 60 
 61     //压缩花
 62     void reset(int u,int anc)
 63     {
 64         while(u!=anc)
 65         {
 66             int v=match[u];
 67             inblossom[base[u]]=1;
 68             inblossom[base[v]]=1;
 69             v=pre[v];
 70             if(base[v]!=anc)pre[v]=match[u];
 71             u=v;
 72         }
 73     }
 74 
 75     void contract(int u,int v,int n)
 76     {
 77         int anc=findancestor(u,v);
 78         //SET(inblossom,0);
 79         memset(inblossom,0,sizeof(inblossom));
 80         reset(u,anc);
 81         reset(v,anc);
 82         if(base[u]!=anc)pre[u]=v;
 83         if(base[v]!=anc)pre[v]=u;
 84         for(int i=1; i<=n; i++)
 85             if(inblossom[base[i]])
 86             {
 87                 base[i]=anc;
 88                 if(!inque[i])
 89                 {
 90                     Q.push_back(i);
 91                     inque[i]=1;
 92                 }
 93             }
 94     }
 95 
 96     bool dfs(int S,int n)
 97     {
 98         for(int i=0; i<=n; i++)pre[i]=-1,inque[i]=0,base[i]=i;
 99         Q.clear();
100         Q.push_back(S);
101         inque[S]=1;
102         while(!Q.empty())
103         {
104             int u=Q.front();
105             Q.pop_front();
106             for(int v=1; v<=n; v++)
107             {
108                 if(g[u][v]&&base[v]!=base[u]&&match[u]!=v)
109                 {
110                     if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n);
111                     else if(pre[v]==-1)
112                     {
113                         pre[v]=u;
114                         if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1;
115                         else
116                         {
117                             u=v;
118                             while(u!=-1)
119                             {
120                                 v=pre[u];
121                                 int w=match[v];
122                                 match[u]=v;
123                                 match[v]=u;
124                                 u=w;
125                             }
126                             return true;
127                         }
128                     }
129                 }
130             }
131         }
132         return false;
133     }
134 
135     void init(int n)
136     {
137         this->n = n;
138         memset(match,-1,sizeof(match));
139         memset(g,0,sizeof(g));
140     }
141 
142     void addEdge(int a, int b)
143     {
144         ++a;
145         ++b;
146         g[a][b] = g[b][a] = 1;
147     }
148 
149     int gao()
150     {
151         int ans = 0;
152         for (int i = 1; i <= n; ++i)
153             if (match[i] == -1 && dfs(i, n))
154                 ++ans;
155         return ans;
156     }
157 } match;
158 
159 int n,m,L;
160 vector<pair<int,int> > node;
161 int dist(pair<int,int> A,pair<int,int> B)
162 {
163     return abs(A.first-B.first)+abs(A.second-B.second);
164 }
165 void init()
166 {
167     node.clear();
168     match.init(m);
169 }
170 void input()
171 {
172     n=m;
173     int u,v;
174     while(m--)
175     {
176         scanf("%d%d",&u,&v);
177         node.push_back(pair<int,int>(u,v));
178     }
179     scanf("%d",&L);
180     pair<int,int> x,y;
181     for(int i=0;i<node.size();i++)
182     {
183         x=node[i];
184         for(int j=0;j<node.size();j++)
185         {
186             if(i==j) continue;
187             y=node[j];
188             if(dist(x,y)<=L) match.addEdge(i,j);
189         }
190     }
191 }
192 void solve()
193 {
194     if(match.gao()*2==n) puts("YES");
195     else puts("NO");
196 }
197 int main()
198 {
199 //    std::ios_base::sync_with_stdio(false);
200 //    freopen("in.cpp","r",stdin);
201     while(~scanf("%d",&m))
202     {
203         init();
204         input();
205         solve();
206     }
207     return 0;
208 }
View Code

 

posted @ 2013-08-21 18:16  xysmlx  阅读(368)  评论(0编辑  收藏  举报