HDU 多校联合练习赛2 Warm up 2 二分图匹配
2013-07-27 21:40
288 查看
Warm up 2
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 656 Accepted Submission(s): 329
Problem Description
Some 1×2 dominoes are placed on a plane. Each dominoe is placed either horizontally or vertically. It's guaranteed the dominoes in the same direction are not overlapped, but horizontal and vertical dominoes may overlap with each other. You task is to remove some dominoes, so that the remaining dominoes do not overlap with each other. Now, tell me the maximum number of dominoes left on the board.
Input
There are multiple input cases.
The first line of each case are 2 integers: n(1 <= n <= 1000), m(1 <= m <= 1000), indicating the number of horizontal and vertical dominoes.
Then n lines follow, each line contains 2 integers x (0 <= x <= 100) and y (0 <= y <= 100), indicating the position of a horizontal dominoe. The dominoe occupies the grids of (x, y) and (x + 1, y).
Then m lines follow, each line contains 2 integers x (0 <= x <= 100) and y (0 <= y <= 100), indicating the position of a horizontal dominoe. The dominoe occupies the grids of (x, y) and (x, y + 1).
Input ends with n = 0 and m = 0.
Output
For each test case, output the maximum number of remaining dominoes in a line.
Sample Input
2 3
0 0
0 3
0 1
1 1
1 3
4 5
0 1
0 2
3 1
2 2
0 0
1 0
2 0
4 1
3 2
0 0
Sample Output
4
6
Source
2013 Multi-University Training Contest 2
Recommend
zhuyuanchen520
题解:
原来是我建图不会建。。。果然是基础功不扎实啊。。
原来就是个普通的最大独立集。 最大独立集的定义就是所选取的点集合中,任意两条边都不相连。 又因为题目中说横着的不会跟横着的相连,竖着的不会跟竖着的相连,所以。这是个相当标准的二分图。就是求X集合跟Y集合的最大独立集。
建造图时,X取的是那0到n-1个骨牌 Y取的是后面的0到m-1个骨牌。。。无语撒。。原来当初我2分图完全弄错了。。
这题解法好像很多。。什么搜索,贪心。。不说了。。。牢记不会建图的教训。。
我提供下我写的3份模板代码吧。。。。
第一份 33MS
#include <cstdio> #include <cstdlib> #include <cstring> #include <cstring> const int maxn=1111; int g[maxn][maxn]; int cx[maxn],cy[maxn],vst[maxn]; int nx,ny; int findpath(int u){ for(int v=0;v<ny;v++){ if(!vst[v]&&g[u][v]){ vst[v]=1; if(cy[v]==-1||findpath(cy[v])){ cy[v]=u,cx[u]=v; return 1; } } } return 0; } int MaxMatch(){ int ret=0; memset(cx,-1,sizeof(cx)); memset(cy,-1,sizeof(cy)); for(int i=0;i<nx;i++) if(cx[i]==-1){ memset(vst,0,sizeof(vst)); if(findpath(i)) ret++; } return ret; } struct node{ int x,y; }mx[maxn],my[maxn]; int main(){ //freopen("1009.in","r",stdin); int n,m; while(scanf("%d %d",&n,&m)&&n+m){ for(int i=0,a,b;i<n;i++){ scanf("%d %d",&a,&b); mx[i].x=a,mx[i].y=b; } for(int i=0,a,b;i<m;i++){ scanf("%d %d",&a,&b); my[i].x=a,my[i].y=b; } memset(g,0,sizeof(g)); for(int i=0,x1,y1;i<n;i++){ x1=mx[i].x,y1=mx[i].y; for(int j=0,x2,y2;j<m;j++){ x2=my[j].x,y2=my[j].y; if(x1==x2&&y1==y2 ||x1==x2&&y1==y2+1 ||x1+1==x2&&y1==y2 ||x1+1==x2&&y1==y2+1) g[i][j]=1; } } nx=n,ny=m; printf("%d\n",n+m-MaxMatch()); } return 0; }
第2份:15MS
#include <cstdlib> #include <cstdio> #include <vector> #include <cstring> #include <iostream> #define clr(x,k) memset((x),(k),sizeof(x)) #define foreach(it,c) for(vi::iterator it = (c).begin();it != (c).end();++it) using namespace std; typedef vector<int> vi; const int maxn=1000; vector<int> gx[maxn]; int cx[maxn],cy[maxn],vst[maxn]; int nx,ny; int findpath_Vector(int u){ foreach(it,gx[u]){ if(!vst[*it]){ vst[*it]=1; if(cy[*it]==-1||findpath_Vector(cy[*it])){ cx[u]=*it; cy[*it]=u; return 1; } } } return 0; } int maxMatch_Vector(){ int ret=0; clr(cx,-1),clr(cy,-1); for(int i=0;i<nx;i++) if(cx[i]==-1){ clr(vst,0); if(findpath_Vector(i)) ret++; } return ret; } struct node{ int x,y; }mx[maxn],my[maxn]; int main(){ // freopen("1009.in","r",stdin); int n,m; while(scanf("%d %d",&n,&m)&&n+m){ for(int i=0,a,b;i<n;i++){ scanf("%d %d",&a,&b); mx[i].x=a,mx[i].y=b; } for(int i=0,a,b;i<m;i++){ scanf("%d %d",&a,&b); my[i].x=a,my[i].y=b; } for(int i=0;i<n;i++) gx[i].clear(); for(int i=0,x1,y1;i<n;i++){ x1=mx[i].x,y1=mx[i].y; for(int j=0,x2,y2;j<m;j++){ x2=my[j].x,y2=my[j].y; if(x1==x2&&y1==y2 ||x1==x2&&y1==y2+1 ||x1+1==x2&&y1==y2 ||x1+1==x2&&y1==y2+1) gx[i].push_back(j); } } nx=n,ny=m; printf("%d\n",n+m-maxMatch_Vector()); } return 0; }
第3份 15MS。 hy这个算法应该会快点的。可能是因为题目有点特殊,没有体现。
#include <cstdlib> #include <cstdio> #include <vector> #include <queue> #include <cstring> #include <iostream> #define clr(x,k) memset((x),(k),sizeof(x)) #define foreach(it,c) for(vi::iterator it = (c).begin();it != (c).end();++it) using namespace std; typedef vector<int> vi; const int INF=1<<28; const int maxn=1000; int cx[maxn],cy[maxn]; vi gx[maxn]; int dx[maxn],dy[maxn]; int dis,nx; int vst[maxn]; bool searchpath(){ queue<int> Q; dis=INF; clr(dx,-1),clr(dy,-1); for(int i=0;i<nx;i++){ if(cx[i]==-1) Q.push(i),dx[i]=0; } while(!Q.empty()){ int u=Q.front();Q.pop(); if(dx[u]>dis) break; foreach(it,gx[u]) if(dy[*it]==-1){ dy[*it]=dx[u]+1; if(cy[*it]==-1) dis=dy[*it]; else{ dx[cy[*it]]=dy[*it]+1; Q.push(cy[*it]); } } } return dis!=INF; } int hop_Findpath_Vector(int u){ foreach(it,gx[u]){ if(!vst[*it]&&dy[*it]==dx[u]+1){//说明这是一条增广路径。但还需判断 vst[*it]=1; if(cy[*it]!=-1&&dy[*it]==dis) //出现这种情况。说明不是增广路, 因为最后一条增路是 cy[v]==-1&&dy[v]==dis continue; if(cy[*it]==-1||hop_Findpath_Vector(cy[*it])){ cy[*it]=u,cx[u]=*it; return 1; } } } return 0; } int hopcroft_MaxMatch_Vector(){ int res=0; clr(cx,-1),clr(cy,-1); while(searchpath()){ clr(vst,0); for(int i=0;i<nx;i++){ if(cx[i]==-1){ res+=hop_Findpath_Vector(i); } } } return res; } struct node{ int x,y; }mx[maxn],my[maxn]; int main(){ //freopen("1009.in","r",stdin); int n,m; while(scanf("%d %d",&n,&m)&&n+m){ for(int i=0,a,b;i<n;i++){ scanf("%d %d",&a,&b); mx[i].x=a,mx[i].y=b; } for(int i=0,a,b;i<m;i++){ scanf("%d %d",&a,&b); my[i].x=a,my[i].y=b; } for(int i=0;i<n;i++) gx[i].clear(); for(int i=0,x1,y1;i<n;i++){ x1=mx[i].x,y1=mx[i].y; for(int j=0,x2,y2;j<m;j++){ x2=my[j].x,y2=my[j].y; if(x1==x2&&y1==y2 ||x1==x2&&y1==y2+1 ||x1+1==x2&&y1==y2 ||x1+1==x2&&y1==y2+1) gx[i].push_back(j); } } nx=n; printf("%d\n",n+m-hopcroft_MaxMatch_Vector()); } return 0; }
如果要达到0MS的话。估计要贪心一下了。
相关文章推荐
- HDU 多校联合练习赛2 Warm up 2 二分图匹配
- hdu 4619 warm up 2 并查集或搜索都可以做出来的题 2013多校联合训练第二场
- HDU 4870 Rating 多校联合练习赛 高斯消元
- 多校联合练习赛6 HDU 4655 Cut Pierces
- 多校联合训练4&&HDU 5763
- hdu 4301 Divide Chocolate (多校联合1)
- hdu 5362 Just A String 2015多校联合训练赛#6 动态规划
- HDU 多校联合第一场
- 2017多校联合第二场 1001题 hdu 6045 Is Derek lying?
- hdu 4324 Triangle LOVE 拓扑排序 多校联合赛(三)第四题
- HDU 多校联合第三场
- HDU 5305 Friends (搜索+剪枝) 2015多校联合第二场
- 2014多校联合六(HDU 4923 HDU 4925 HDU 4927 HDU 4930)
- hdu 5387 Clock 2015多校联合训练赛#8
- 2013 多校联合4 1011 Fliping game (hdu 4642)
- hdu多校联合Peter's Hobby
- HDU 4638 2013多校联合第4场 G-Group
- 2014多校联合八(HDU 4945 HDU 4946 HDU 4948 HDU 4950 HDU 4951 HDU 4952)
- HDU 4658 2013 多校联合赛第6场 Integer Partition
- 2014多校联合第9场1011题||hdu 4970 树状数组