HDU 4619 —— Warm up 2(二分图最大匹配)
2014-03-07 12:52
585 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4619
最近学了二分匹配,这块我是看kuangbin大神的文章的:/article/4680097.html
个人觉得他博客的文章很赞,很多总结也写得很好,强力推荐!
平面上有很多1X2的多米诺骨牌,横放或竖放,相同方向的不会重叠。现在要取走一些,使得剩下的两两没有重叠,问最多能剩下多少个。
有两种考虑的方法,一种是每块牌看作一个点,有重叠到的两块骨牌之间就连一条线,那么问题就是求最大独立集,最大独立集=总点数-最大匹配。
另一种就是将每个格点(每个骨牌占据两个格点)当作一个点,同一块骨牌覆盖到的格点就连一条线,那么问题就是对这些格点求一个最大匹配。
前者可以看作有N+M个点,后者最多是2*(N+M)个点。
但前者构图的时候每个骨牌都要去遍历另一种骨牌,构图的复杂度是O(NM),这种做法在kuangbin的博客上也有;
后者则只是在读入骨牌的时候直接构图,不用考虑其他骨牌,复杂度是O(N+M),但相对的后期处理的点就比较多,我采用的是这种;
对于每个坐标(x,y),因为0<=x<=100 ,0<=y<=100,所以每个坐标可以映射成一个数z=x*101+y
用一个f[z]来记录这块格点对应的编号,从1开始,因为N和M都不超过1000,所以覆盖到的最多4000个,如果不整理编号总共要101*101个点,但其中很多是空白的。
然后就是构图求最大匹配,最后的答案记得除以2。
二分匹配用的是Hopcroft-Carp算法。
最近学了二分匹配,这块我是看kuangbin大神的文章的:/article/4680097.html
个人觉得他博客的文章很赞,很多总结也写得很好,强力推荐!
平面上有很多1X2的多米诺骨牌,横放或竖放,相同方向的不会重叠。现在要取走一些,使得剩下的两两没有重叠,问最多能剩下多少个。
有两种考虑的方法,一种是每块牌看作一个点,有重叠到的两块骨牌之间就连一条线,那么问题就是求最大独立集,最大独立集=总点数-最大匹配。
另一种就是将每个格点(每个骨牌占据两个格点)当作一个点,同一块骨牌覆盖到的格点就连一条线,那么问题就是对这些格点求一个最大匹配。
前者可以看作有N+M个点,后者最多是2*(N+M)个点。
但前者构图的时候每个骨牌都要去遍历另一种骨牌,构图的复杂度是O(NM),这种做法在kuangbin的博客上也有;
后者则只是在读入骨牌的时候直接构图,不用考虑其他骨牌,复杂度是O(N+M),但相对的后期处理的点就比较多,我采用的是这种;
对于每个坐标(x,y),因为0<=x<=100 ,0<=y<=100,所以每个坐标可以映射成一个数z=x*101+y
用一个f[z]来记录这块格点对应的编号,从1开始,因为N和M都不超过1000,所以覆盖到的最多4000个,如果不整理编号总共要101*101个点,但其中很多是空白的。
然后就是构图求最大匹配,最后的答案记得除以2。
二分匹配用的是Hopcroft-Carp算法。
#include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; #define pb push_back #define maxn 4001 const int inf = 0x7fffffff; inline void IN(int& x){ char c=getchar(); while(c<48 || c>57) c=getchar(); x=0; while(c>=48 && c<=57){ x=x*10+c-48; c=getchar(); } } vector<int> V[maxn]; int n, dis; int f[20000]; int dx[maxn], dy[maxn], Mx[maxn], My[maxn]; bool vis[maxn]; bool search(){ queue<int> Q; dis=inf; memset(dx,-1,sizeof(dx)); memset(dy,-1,sizeof(dy)); for(int i=1; i<=n; i++){ if(Mx[i]==-1){ dx[i]=0; Q.push(i); } } while(!Q.empty()){ int u=Q.front(); Q.pop(); if(dx[u]>dis) break; for(int i=0; i<V[u].size(); i++){ int j=V[u][i]; if(dy[j]!=-1) continue; dy[j] = dx[u]+1; if(My[j]==-1) dis=dy[j]; else{ dx[My[j]] = dy[j]+1; Q.push(My[j]); } } } return (dis!=inf); } bool dfs(int x){ for(int i=0; i<V[x].size(); i++){ int j= V[x][i]; if(vis[j] || dy[j]!=dx[x]+1) continue; vis[j]=1; if(My[j]!=-1 && dy[j]==dis) continue; if(My[j]==-1 || dfs(My[j])){ My[j]=x; Mx[x]=j; return 1; } } return 0; } int MaxMatch(){ int ans=0; memset(Mx,-1,sizeof(Mx)); memset(My,-1,sizeof(My)); while(search()){ memset(vis,0,sizeof(vis)); for(int i=1; i<=n; i++){ if(Mx[i]==-1 && dfs(i)) ans++; } } return ans; } int main(){ while(1){ int a, b, x, y, z1, z2; IN(a); IN(b); if(!(a||b)) break; memset(f,0,sizeof(f)); n=0; while(a--){ IN(x); IN(y); z1 = x*101+y; z2 = z1+101; if(!f[z1]){ f[z1]=++n; V .clear(); } z1 = f[z1]; if(!f[z2]){ f[z2]=++n; V .clear(); } z2 = f[z2]; V[z1].pb(z2); V[z2].pb(z1); } while(b--){ IN(x); IN(y); z1 = x*101+y; z2 = z1+1; if(!f[z1]){ f[z1]=++n; V .clear(); } z1 = f[z1]; if(!f[z2]){ f[z2]=++n; V .clear(); } z2 = f[z2]; V[z1].pb(z2); V[z2].pb(z1); } printf("%d\n", MaxMatch()>>1); } return 0; }
相关文章推荐
- hdu 4619 Warm up 2 ( 二分图最大匹配 )
- hdu 4619 Warm up 2 ( 二分图最大匹配 )
- hdu 4619 Warm up 2(二分图最大匹配)
- hdu 4619 Warm up 2 (二分图最大独立集)
- HDU 4619 Warm up 2(贪心、并查集 | 二分图最大独立集)
- hdu 4619 二分图最大匹配 ——最大独立集
- HDU 4619 Warm up 2(最大流或二分匹配)
- hdu 4619 Warm up 2(最大独立点集,二分匹配,4级)
- HDU 2444 The Accomodation of Students 二分图判定+最大匹配
- hdu 4619 匈牙利算法 求最大匹配 2013 Multi-University Training Contest 2
- hdu 1083 Courses 二分图最大匹配
- hdu - 2063 - 过山车(二分图最大匹配)
- hdu 2813 二分图最大权匹配 非完全匹配
- hdu 4160 Dolls--最小点集覆盖=V-二分图最大匹配
- HDU 1507 Uncle Tom's Inherited Land*(二分图最大匹配:输出一组解)
- hdu 2063 二分图—最大匹配
- HDU - 1083 : Courses(匈牙利算法,二分图最大匹配)
- hdu 5285 wyh2000 and pupil 二分图染色发判定,求最大匹配
- hdu 2444(二分图判断+最大匹配)
- HDU 2444 黑白染色判二分图+二分最大匹配