码迷,mamicode.com
首页 > 其他好文 > 详细

网络流:棋盘V

时间:2018-07-31 17:27:37      阅读:218      评论:0      收藏:0      [点我收藏+]

标签:内存   ref   print   dmi   insert   graph   auto   编号   sam   

问题 A: 棋盘V

时间限制: 1 Sec  内存限制: 128 MB
提交: 192  解决: 7

[提交] [状态] [讨论版] [命题人:admin]

题目描述

有一块棋盘,棋盘的边长为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。

 

跑一遍最小费用最大流即可,把每一个坐标看作是"花费"为1的路径,分别从源点拉出路径到x做出"花费"为0,"流量"为cnt[x]的路径,从y到汇点拉出"花费"为0,"流量"为cnt[y]的路径。

 

#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <unordered_map>
#include <set>

using namespace std;
#define N 10005
#define inf 0x3f3f3f3f
struct E{
    int to,next,val,cost;
};
class graphic{
public:
    void clear(){
        cnt = 0;
        res = 0;
        st = en = 0;
        memset(head,-1, sizeof(head));
    }
    void add(int u,int v,int w,int c){
        _add(u,v,w,c);
        _add(v,u,0,-c);
    }
    void setST(int a,int b){
        st = a;
        en = b;
    }
    void Dinic(){
        while (spfa())dfs(st,inf);
    }
    void show(){
        cerr<<cnt<<endl;
        for(int i = 0 ; i < cnt ; ++i){
            printf("%d %d\n",i,edge[i].to);
        }
        cerr<<endl;
    }
    int ans(){ return res;}
private:
    int st,en;///源点,汇点
    int head[N];
    int cnt;
    E edge[N];
    bool spfaVis[N];
    bool dfsVis[N];
    int dis[N];
    int res;
    void _add(int u,int v,int w,int c){
        edge[cnt].to = v;
        edge[cnt].next = head[u];
        edge[cnt].val = w;
        edge[cnt].cost = c;
        head[u] = cnt++;
    }
    bool spfa(){
        memset(spfaVis,0, sizeof(spfaVis));
        memset(dfsVis,0, sizeof(dfsVis));
        queue<int>q;
        q.push(st);
        memset(dis,inf, sizeof(dis));
        dis[st] = 0;
        spfaVis[st] = true;
        while (!q.empty()){
            int u = q.front();
            q.pop();
            spfaVis[u] = false;
            for(int i = head[u],v ; ~i ; i = edge[i].next){
                v = edge[i].to;
                if(edge[i].val and dis[v]>dis[u] + edge[i].cost){
                    dis[v] = dis[u] + edge[i].cost;
                    if(!spfaVis[v]) {
                        q.push(v);
                        spfaVis[v] = true;
                    }
                }
            }
        }
        return dis[en]<inf;
    }
    int dfs(int u,int f){
        if(en==u){
            res+=dis[en]*f;
            return f;
        }
        int ret = 0;
        dfsVis[u] = true;
        for(int i = head[u],v ; ~i ; i = edge[i].next){
            v = edge[i].to;
            if(edge[i].val and !dfsVis[v] and dis[v] == dis[u] + edge[i].cost){
                int temp = dfs(v,min(edge[i].val,f-ret));
                edge[i].val-=temp;
                edge[i^1].val+=temp;
                ret+=temp;
                if(ret==f)return ret;
            }
        }
        return ret;
    }
};
graphic ss;
unordered_map<int,int>xx,yy;///坐标点到序号的映射
int cnt[N];///坐标出现次数
bool have[205][205];
set<int>sx,sy;
int main(){
    ss.clear();
    int n,tolx,toly;
    scanf("%d",&n);
    tolx = 1,toly = n*2+1;
    int x,y;
    for(int i = 0 ; i < n ; ++i){
        scanf("%d %d",&x,&y);
        if(!xx[x])xx[x] = tolx++;
        if(!yy[y])yy[y] = toly++;
        have[xx[x]][yy[y]] = true;
        ++cnt[xx[x]];
        ++cnt[yy[y]];
        sx.insert(xx[x]);
        sy.insert(yy[y]);
    }
    ss.setST(0,toly);
    for(auto &i: xx){
        ss.add(0,i.second,cnt[i.second],0);
    }
    for(auto &i: yy){
        ss.add(i.second,toly,cnt[i.second],0);
    }
    for(auto i:sx){
        for(auto j:sy){
            if(have[i][j]){
                ss.add(i,j,1,1);
            }
            else ss.add(i,j,1,0);
        }
    }
    ss.Dinic();
    cout<<ss.ans()<<endl;
}

 

 

 

 

网络流:棋盘V

标签:内存   ref   print   dmi   insert   graph   auto   编号   sam   

原文地址:https://www.cnblogs.com/DevilInChina/p/9396296.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!