链接
http://acm.hdu.edu.cn/showproblem.php?pid=1045
题意
在 $n*n$ 的图上有一些围墙,放置一些大炮,大炮能攻击上下左右任何距离的其他大炮,但不能穿过围墙,求最多能放多少个互相不会攻击的大炮
思路
按行对每个连通块染色,按列对每个连通块染色
对每个点所在的行连通块与列连通块之前连边
跑二分图最大匹配
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| #include <bits/stdc++.h> #define SZ(x) (int)(x).size() #define ALL(x) (x).begin(),(x).end() #define PB push_back #define EB emplace_back #define MP make_pair #define FI first #define SE second using namespace std; typedef double DB; typedef long long LL; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<PII> VPII;
const int N=5; int n,cnt,match[N*N],col_x[N][N],col_y[N][N]; bool st[N*N]; char s[N][N]; VI g[N*N]; bool dfs(int u) { for(auto v:g[u]) { if(st[v]) continue; st[v]=true; if(match[v]==-1||dfs(match[v])) { match[u]=v; match[v]=u; return true; } } return false; } int main() { while(~scanf("%d",&n)&&n) { for(int i=0;i<n;i++) scanf("%s",s[i]); cnt=0; for(int i=0;i<n;i++) for(int j=0;j<n;j++) { if(j==0||s[i][j-1]=='X') cnt++; col_x[i][j]=cnt; } for(int j=0;j<n;j++) for(int i=0;i<n;i++) { if(i==0||s[i-1][j]=='X') cnt++; col_y[i][j]=cnt; } for(int i=1;i<=cnt;i++) g[i].clear(); for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(s[i][j]!='X') { g[col_x[i][j]].PB(col_y[i][j]); g[col_y[i][j]].PB(col_x[i][j]); } int res=0; for(int i=1;i<=cnt;i++) match[i]=-1; for(int i=1;i<=cnt;i++) { if(match[i]!=-1) continue; for(int j=1;j<=cnt;j++) st[j]=false; if(dfs(i)) res++; } printf("%d\n",res); } return 0; }
|