【二分圖匹配】HDU
阿新 • • 發佈:2018-12-09
題意:
給出一張圖,‘X’代表牆,‘.’ 代表空地。在空地上放一些炮塔,炮塔不能處在同一行同一列,除非被牆隔開。問最多能放多少個炮塔。
題解:
這題其實可以二進位制暴力模擬去做,但也可以用二分圖來做。
考慮不存在牆的情況,那麼可以把行和列當作兩邊的點,中間放炮塔當作邊,進行二分圖匹配即可。
如果存在牆,牆的兩側其實就相當於是兩個互不相關的點。而對於一連串的空地(即中間不存在牆),由於只能放一個炮臺的特性,所以相當於一個點。
那麼就首先從列出發,對每一列空地縮點並染色。然後從行出發去縮點,並與所染色的對應列連邊。最後進行二分圖匹配即可。
#include<bits/stdc++.h> using namespace std; const int N=1e3+7; struct Edge{ int u,v,w,nxt; Edge(int u=0,int v=0,int w=0,int nxt=0):u(u),v(v),w(w),nxt(nxt){} }e[N*2]; int p[N],edn; void add(int u,int v,int w){ e[++edn]=Edge(u,v,w,p[u]);p[u]=edn; e[++edn]=Edge(v,u,w,p[v]);p[v]=edn; } int match[N],vis[N]; int n,m; bool dfs(int u){ for(int i=p[u];~i;i=e[i].nxt){ int v=e[i].v; if(vis[v]) continue; vis[v]=1; if(match[v]==-1||dfs(match[v])){ match[v]=u; return true; } } return false; } char mp[N][N],col[N][N]; int main() { int n; while(scanf("%d",&n)!=EOF){ if(n==0) break; memset(match,-1,sizeof(match)); memset(p,-1,sizeof(p));edn=-1; for(int i=1;i<=n;i++) scanf("%s",mp[i]+1); int top=1; for(int j=1;j<=n;j++){ for(int i=1;i<=n;i++){ if(mp[i][j]=='X') top++; else col[i][j]=top; } top++; } top=1; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(mp[i][j]=='X') top++; else add(top,col[i][j]+100,1); } top++; } int ans=0; for(int i=1;i<=top;i++){ memset(vis,0,sizeof(vis)); if(dfs(i)) ans++; } printf("%d\n",ans); } return 0; }