问题 A: 棋盘V
时间限制: 1 Sec 内存限制: 128 MB提交: 150 解决: 3
[提交] [状态] [讨论版] [命题人:]
题目描述
有一块棋盘,棋盘的边长为100000,行和列的编号为1到100000。棋盘上有n个特殊格子,任意两个格子的位置都不相同。
现在小K要猜哪些格子是特殊格子。她知道所有格子的横坐标和纵坐标,但并不知道对应关系。换言之,她只有两个数组,一个存下了所有格子的横坐标,另一个存下了所有格子的纵坐标,而且两个数组都打乱了顺序。当然,小K猜的n个格子的位置也必须都不相同。
请求出一个最大的k,使得无论小K怎么猜,都能猜对至少k个格子的位置。
现在小K要猜哪些格子是特殊格子。她知道所有格子的横坐标和纵坐标,但并不知道对应关系。换言之,她只有两个数组,一个存下了所有格子的横坐标,另一个存下了所有格子的纵坐标,而且两个数组都打乱了顺序。当然,小K猜的n个格子的位置也必须都不相同。
请求出一个最大的k,使得无论小K怎么猜,都能猜对至少k个格子的位置。
输入
输入数据第一行包含一个整数n。
接下来n行,每行描述一个特殊格子的位置。第i行含有两个整数xi和yi ,代表第i个格子的坐标。保证任意两个格子的坐标都不相同。
接下来n行,每行描述一个特殊格子的位置。第i行含有两个整数xi和yi ,代表第i个格子的坐标。保证任意两个格子的坐标都不相同。
输出
输出一行,包含一个整数,代表最大的k。
样例输入
2
1 1
2 2
样例输出
0
提示
小K有可能会猜(1,2),(2,1),此时一个都没对
对于30%的数据,n≤8。
另外有5%的数据,所有横坐标和纵坐标均不相同。
另外有15%的数据,所有横坐标或者纵坐标均不相同。
对于100%的数据,n≤50,1≤xi,yi≤100000。
#include <iostream> #include <string> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <vector> #include <queue> #include <deque> #include <stack> #include <map> #define LL long long #define equal == #define inf 0x3f3f3f3f #define fr first #define sc second #define range(i,a,b) for(auto i=a;i<=b;++i) #define itrange(i,a,b) for(auto i=a;i!=b;++i) #define rerange(i,a,b) for(auto i=a;i>=b;--i) #define fill(arr,tmp) memset(arr,tmp,sizeof(arr)) using namespace std; const int mxn=int(1e5+5); int n,x[mxn],y[mxn],p[mxn],cnt,flag[1005][1005],ans; namespace MCMF{ struct edge{ int head,to,nxt,cost,weight; }edges[mxn]; bool vis1[mxn],vis2[mxn]; int S,T,sum1[mxn],sum2[mxn],d[mxn],tol=2; void add(int x,int y,int z,int p){ edges[tol].cost=p;edges[tol+1].cost=-p; edges[tol].weight=z;edges[tol+1].weight=0; edges[tol].to=y;edges[tol+1].to=x; edges[tol].nxt=edges[x].head;edges[tol+1].nxt=edges[y].head; edges[x].head=tol++;edges[y].head=tol++; } bool spfa(){ fill(vis1,0);fill(vis2,0);fill(d,inf); queue<int>q; q.push(S); d[S]=0; vis1[S]=1; while(not q.empty()){ int head=q.front(); q.pop(); vis1[head]=false; for(int i=edges[head].head;i;i=edges[i].nxt){ int to=edges[i].to; if(edges[i].weight and d[to]>d[head]+edges[i].cost){ d[to]=d[head]+edges[i].cost; if(!vis1[to]){ vis1[to]=true; q.push(to); } } } } return d[T]!=inf; } int dfs(int to,int fs){ if(to equal T){ ans+=d[to]*fs; return fs; } int ret=0; vis2[to]=true; for(int i=edges[to].head;i;i=edges[i].nxt){ int tmp=edges[i].to; if(edges[i].weight and not vis2[tmp] and d[tmp] equal d[to]+edges[i].cost){ int ntmp(dfs(tmp,min(fs-ret,edges[i].weight))); edges[i].weight-=ntmp; edges[i^1].weight+=ntmp; ret+=ntmp; if(ret==fs)return ret; } } return ret; } } void init(){ scanf("%d",&n); MCMF::S=(n<<2)+1; MCMF::T=MCMF::S+1; range(i,1,n){ scanf("%d%d",x+i,y+i); p[++cnt]=*(x+i); p[++cnt]=*(y+i); } sort(p+1,p+1+cnt); cnt=int(unique(p+1,p+1+cnt)-p-1); range(i,1,n){ x[i]=int(lower_bound(p+1,p+1+cnt,x[i])-p); y[i]=int(lower_bound(p+1,p+1+cnt,y[i])-p); using namespace MCMF; ++sum1[x[i]]; ++sum2[y[i]]; flag[x[i]][y[i]]=true; } } void solve(){ using namespace MCMF; range(i,1,cnt){ if(sum1[i])add(S,i,sum1[i],0); if(sum2[i])add(i+(n<<1),T,sum2[i],0); } range(i,1,cnt) range(j,1,cnt){ if(flag[i][j])add(i,j+(n<<1),1,1); else add(i,j+(n<<1),1,0); } while(spfa())dfs(S,inf); printf("%d ",ans); } int main() { init(); solve(); return 0; }