棋盘V

问题 A: 棋盘V

时间限制: 1 Sec   内存限制: 128 MB
提交: 150   解决: 3
[ 提交] [ 状态] [ 讨论版] [命题人: ]

题目描述

有一块棋盘,棋盘的边长为100000,行和列的编号为1到100000。棋盘上有n个特殊格子,任意两个格子的位置都不相同。
现在小K要猜哪些格子是特殊格子。她知道所有格子的横坐标和纵坐标,但并不知道对应关系。换言之,她只有两个数组,一个存下了所有格子的横坐标,另一个存下了所有格子的纵坐标,而且两个数组都打乱了顺序。当然,小K猜的n个格子的位置也必须都不相同。
请求出一个最大的k,使得无论小K怎么猜,都能猜对至少k个格子的位置。

输入

输入数据第一行包含一个整数n。
接下来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\n",ans);
}
int main() {
    init();
    solve();
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Rhythm-/p/9395823.html