标签:二分匹配
题意:在n×m的方格中,‘#’代表iceberg,‘*‘代表ocean,‘o’代表floating ice。战舰只能放在ocean上,在同一行或者同一列不能放两
个战舰除非它们中间有iceberg,求最多能放多少战舰。
思路:二分匹配。每行中连续为‘*‘的作为X集合中一个点,同样,将每列中连续为‘*‘的点作为Y集合中的一个点。对原图中每个‘*‘,将其对应的X集合和Y集合中的标号建边,便形成了二分图,对该图求最大匹配。详见代码:
/********************************************************* file name: hdu5093.cpp author : kereo create time: 2015年02月02日 星期一 15时11分33秒 *********************************************************/ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<set> #include<map> #include<vector> #include<stack> #include<cmath> #include<string> #include<algorithm> using namespace std; typedef long long ll; const int sigma_size=26; const int N=50+50; const int MAXN=2500+50; const int inf=0x3fffffff; const double eps=1e-8; const int mod=100000000+7; #define L(x) (x<<1) #define R(x) (x<<1|1) #define PII pair<int, int> #define mk(x,y) make_pair((x),(y)) int n,m,edge_cnt; char mp[N][N]; int head[MAXN],vis[MAXN],link[MAXN],x[N][N],y[N][N]; struct Edge{ int v,next; }edge[MAXN]; void init(){ edge_cnt=0; memset(link,-1,sizeof(link)); memset(head,-1,sizeof(head)); } void addedge(int u,int v){ edge[edge_cnt].v=v; edge[edge_cnt].next=head[u]; head[u]=edge_cnt++; } bool dfs(int u){ for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(vis[v]) continue; vis[v]=1; if(link[v] == -1 || dfs(link[v])){ link[v]=u; return true; } } return false; } int main(){ //freopen("in.txt","r",stdin); int T; scanf("%d",&T); while(T--){ init(); scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%s",mp[i]); int cnt1=0,cnt2=0; for(int i=0;i<n;i++){ int flag=1; for(int j=0;j<m;){ if(mp[i][j] == '*'){ if(flag) ++cnt1; flag=0; while(j<m && mp[i][j] == '*'){ x[i][j]=cnt1; j++; } } else if(mp[i][j] == 'o'){ while(j<m && mp[i][j] == 'o') j++; } else{ flag=1; while(j<m && mp[i][j] == '#') j++; } } } for(int j=0;j<m;j++){ int flag=1; for(int i=0;i<n;){ if(mp[i][j] == '*'){ if(flag) ++cnt2; flag=0; while(i<n && mp[i][j] == '*'){ y[i][j]=cnt2; i++; } } else if(mp[i][j] == 'o'){ while(i<n && mp[i][j] == 'o') i++; } else{ flag=1; while(i<n && mp[i][j] == '#') i++; } } } for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(mp[i][j] == '*') addedge(x[i][j],y[i][j]); int ans=0; for(int i=1;i<=cnt1;i++){ memset(vis,0,sizeof(vis)); if(dfs(i)) ans++; } printf("%d\n",ans); } return 0; }
标签:二分匹配
原文地址:http://blog.csdn.net/u011645923/article/details/43409407