• 网络流:棋盘V


    问题 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
    ",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;
    }
  • 相关阅读:
    PrintStream标准字节输出流
    DataInputStream数据字节专属输入流
    java.io.DateOutputStream:数据专属字节输出流
    BufferedWriter带有缓冲区的输出流 及 OutputStreamWriter转换流
    BufferedReader带有缓冲区的输入流 及 InputStreamReader转换流
    FileWriter输出文本流
    FileReader输入文本流
    使用FileInputStream 和 FileOutputStream 进行copy流 和 使用FileReader 和 FileWriter 进行 copy流案例:
    FileOutputStream输出字符流
    window docker的安装
  • 原文地址:https://www.cnblogs.com/DevilInChina/p/9396296.html
Copyright © 2020-2023  润新知