• [LUOGU] P4251 [SCOI2015]小凸玩矩阵


    行列看成点,格子看成边,二分一个边权,删去大于它的边,新图上的最大流>k则答案可以更优,小于k则调整左边界。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    using namespace std;
    
    inline int rd(){
        int ret=0,f=1;char c;
        while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
        while(isdigit(c))ret=ret*10+c-'0',c=getchar();
        return ret*f;
    }
    
    const int MAXN=256*256;
    const int M=256*256*2;
    
    struct Edge{
        int next,to,f;
    }e[M<<1];
    int ecnt=1,head[MAXN];
    inline void add(int x,int y,int f){
        e[++ecnt].next = head[x];
        e[ecnt].to = y;
        e[ecnt].f = f;
        head[x] = ecnt;
    }
    
    int n,m,num;
    int a[256][256];
    int b[MAXN],p;
    
    int dep[MAXN];
    queue<int> Q;
    bool bfs(int s,int t){
        memset(dep,0,sizeof(dep));
        dep[s]=1;Q.push(s);
        while(!Q.empty()){
            int top=Q.front();Q.pop();
            for(int i=head[top];i;i=e[i].next){
                int v=e[i].to;
                if(dep[v]||!e[i].f) continue;
                dep[v]=dep[top]+1;Q.push(v);
            }
        }
        return dep[t];
    }
    int cur[MAXN];
    int dfs(int x,int flow,int t){
        if(x==t) return flow;
        int used=0,tmp;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(dep[v]!=dep[x]+1) continue;
            tmp=dfs(v,min(flow-used,e[i].f),t);
            e[i].f-=tmp;e[i^1].f+=tmp;used+=tmp;
            if(used==flow) return flow;
            if(e[i].f) cur[x]=i;
        }
        if(!used) dep[x]=-1;
        return used;
    }
    int dinic(int s,int t){
        int ret=0;
        while(bfs(s,t)){
            memcpy(cur,head,sizeof(head));
            ret+=dfs(s,1<<30,t);
        }
        return ret;
    }
    
    int main(){
        n=rd();m=rd();num=rd();
        int S=n*m+1,T=n*m+2; 
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                b[++p]=a[i][j]=rd();
            }
        }
        int ans=1<<30;
        sort(b+1,b+1+p);
        int l=1,r=p;
        while(l<=r){
            int mid=l+r>>1;
            ecnt=1;
            memset(head,0,sizeof(head));
            for(int i=1;i<=n;i++)add(S,i,1),add(i,S,0);
            for(int i=1;i<=m;i++)add(i+n,T,1),add(T,i+n,0);
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    if(a[i][j]>b[mid]) continue;
                    add(i,j+n,1);
                    add(j+n,i,0);
                }
            }
            int tmp=dinic(S,T);
            if(tmp>=n-num+1) r=mid-1,ans=b[mid];
            else l=mid+1;
        }
        cout<<ans;
        return 0;
    }
    未经许可,禁止搬运。
  • 相关阅读:
    epoll使用(转)
    8、多线程小结(1)(转)
    9、多线程小结(2)(转)
    长连接和短连接(转)
    5、线程终止方式:(转)
    linux中read,write和recv,send的区别(转)
    数据访问函数库的使用方法(二)—— 获取记录集和使用事务的方法
    我想到的几句话。
    关于博克园T恤的一点想法。
    我自己写的一个分页控件(源码和演示代码)PostBack分页版 for vs2003、SQL Server
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9534833.html
Copyright © 2020-2023  润新知