[Scoi2015]小凸玩矩阵

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define N 1000005
#define inf 0x3f3f3f3f
using namespace std;

void read(int &s){
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar());
    for(s=0;isdigit(ch);s=s*10+ch-'0',ch=getchar());
}

struct node{
    int to,nxt,cap;
};
int que[N];
int h,qt;

struct Dinic{
    node e[N];
    int n,m,s,t,tot;
    int d[N],cur[N],vis[N],head[N];
    Dinic(){tot=1;}
    void add(int f,int t,int c){
        e[++tot].to=t;
        e[tot].nxt=head[f];
        e[tot].cap=c;
        head[f]=tot;
        e[++tot].to=f;
        e[tot].nxt=head[t];
        e[tot].cap=0;
        head[t]=tot;
    }
    bool bfs(){
        memset(vis,false,sizeof(vis));
        for(int i=0;i<=n;++i)cur[i]=head[i];
        que[qt=1]=s,h=0;int top,to;d[s]=0;vis[s]=1;
        while(h<qt){
            top=que[++h];
            for(int i=head[top];i;i=e[i].nxt)
                if(!vis[e[i].to]&&e[i].cap){
                    to=e[i].to;que[++qt]=to;
                    vis[to]=true;d[to]=d[top]+1;
                    if(to==t)return true;
                }
        }
        return vis[t];
    }
    int dfs(int x,int fl){
        if(x==t)return fl;
        int flow=0,f;
        for(int i=cur[x];i;i=e[i].nxt)
            if(d[e[i].to]==d[x]+1)
                if(f=dfs(e[i].to,min(fl,e[i].cap))){
                    e[i].cap-=f;
                    e[i^1].cap+=f;
                    flow+=f;fl-=f;
                    if(fl<=0)break;
                }
        if(fl)d[x]=-1;
        return flow;
    }
    int dinic(int s,int t){
        this->s=s;
        this->t=t;
        int ans=0;
        while(bfs())
            ans+=dfs(s,inf);
        return ans;
    }
};
int n,m,k,a,b,c;
int map[105][105];
bool can(int x){
    cout<<x;
    Dinic f;f.n=1000;
    for(int i=1;i<=n;++i)
        f.add(1,1+i,1);
    for(int i=1;i<=m;++i)
        f.add(1+n+i,1+n+m+1,1);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            if(map[i][j]<=k)
                f.add(1+i,1+n+j,1);
    int ans=f.dinic(1,1+n+m+1);
    cout<<x<<' '<<ans<<endl;
    return ans<=n-k+1;
}

int twomillon(int l,int r){
    cout<<l<<' '<<r<<endl;
    int mid=0;
    while(l<=r){
        mid=(l+r)>>1;
        if(can(mid))
            l=mid+1;
        else r=mid-1;
    }
    return l;
}

int main(){
    int maxl=0;
    read(n);read(m);read(k);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j){
            read(map[i][j]);
            maxl=max(map[i][j],maxl);
        }
    cout<<twomillon(1,maxl);
    return 0;
}
原文地址:https://www.cnblogs.com/qdscwyy/p/8092968.html