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 }