比赛的时候没有想出来怎么做,是钢牛写的,然后就下来看了一眼题解,二分图匹配,然后就写出来了。。。但是等了几天突然看到题想到的还是贪心,然后就是没有想到二分匹配上面去,以至于又想了好久好久。。。然后我自己都无语了,还是先想想贪心怎么做!!!
说下二分匹配的思路:一个格子最多可以由一个竖着的牌和一个横着的牌共同占有,我们只能选择其中的一个的,所以根据共同占有的格子数来进行建图,找到最大匹配数,最多可以放的牌就是从的牌数减去最大匹配的个数的。下面是代码:
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<stack> #include<vector> #include<climits> #include<map> using namespace std; #define rep(i,n) for(int i=0; i<(n); ++i) #define repf(i,n,m) for(int i=(n); i<=(m); ++i) #define repd(i,n,m) for(int i=(n); i>=(m); --i) #define ll long long #define inf 1000000000 #define exp 0.000000001 #define N 2010 struct node { int x1,y1,x2,y2; node(){}; node(int _x1,int _y1,int _x2,int _y2):x1(_x1),y1(_y1),x2(_x2),y2(_y2){} }; vector<node>a; int n,m; vector<int>vec[N]; bool vis[N]; int next[N]; bool find(node a,node b) { if(a.x1==b.x1 && a.y1==b.y1) return false; if(a.x1==b.x2 && a.y1==b.y2) return false; if(a.x2==b.x1 && a.y2==b.y1) return false; if(a.x2==b.x2 && a.y2==b.y2) return false; return true; } bool fin(int t) { rep(i,vec[t].size()) { int m=vec[t][i]; if(vis[m]==false) { vis[m]=true; if(next[m]==-1 || fin(next[m])) { next[m]=t; return true; } } } return false; } int sum() { memset(next,-1,sizeof(next)); int m=0; rep(i,n) { memset(vis,false,sizeof(vis)); if(fin(i)) m++; } return m; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { if(n==0 && m==0) break; rep(i,n+m) vec[i].clear(); int x,y; a.clear(); int nn=0; repf(i,1,n) { scanf("%d%d",&x,&y); { a.push_back(node(x,y,x+1,y)); } } repf(i,1,m) { scanf("%d%d",&x,&y); a.push_back(node(x,y,x,y+1)); } rep(i,n+m) repf(j,i+1,n+m-1) if(!find(a[i],a[j])) // cout<<i<<" "<<j<<endl, vec[i].push_back(j);//vec[j].push_back(i); n=n+m; // cout<<n<<endl; int mm=sum(); printf("%d\n",n-mm); } return 0; }