zoukankan      html  css  js  c++  java
  • 题解 【SCOI2015】小凸玩矩阵

    题面

    解析

    这题其实也是网络流建图。。

    首先,转换下思路,

    求第k大的数的最小值,

    其实就是求一个最小的值,

    使选取的点中能有(n-k+1)个的值比它小。

    因此,可以采用二分答案,

    每次判断一个值,

    将比它小的点加到图中跑最大流,

    看流量是否大于(n-k+1)。

    那么,怎么连边呢?

    其实,我们可以每一行连源点,流量为1,

    每一列连汇点,流量为1,

    中间源点与汇点连INF。

    最后判断就能AC了!

    上AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    inline int read(){
        int sum=0,f=1;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
        return f*sum;
    }
    
    const int INF=0x3f3f3f3f;
    struct node{
        int next,to,v;
    }e[1000001];
    int n,k,m,ans,s,t;
    int a[1001][1001];
    int maxn=0;
    int head[100001],cnt;
    int d[100001],cur[100001];
    
    void add(int x,int y,int v){
        e[++cnt].to=head[x];e[cnt].next=y;
        e[cnt].v=v;head[x]=cnt;
        e[++cnt].to=head[y];e[cnt].next=x;
        e[cnt].v=0;head[y]=cnt;    
    }
    
    bool bfs(){    
        memset(d,0,sizeof(d));
        memcpy(cur,head,sizeof(cur));
        queue <int>    que;
        que.push(s);
        d[s]=1;
        while(!que.empty()){
            int x=que.front();
            que.pop();
            for(int i=head[x];i;i=e[i].to){
                int k=e[i].next;
                if(!e[i].v||d[k]) continue;
                d[k]=d[x]+1;
                que.push(k);
            }
        }
        return d[t];
    }
    
    int dfs(int x,int mi){
        if(x==t||!mi) return mi;
        int flow=0;
        for(int &i=cur[x];i;i=e[i].to){
            int k=e[i].next;
            if(!e[i].v||d[k]!=d[x]+1) continue;
            int ret=dfs(k,min(mi,e[i].v));
            flow+=ret;mi-=ret;
            e[i].v-=ret;e[i^1].v+=ret;
            if(!mi) break;
        }
        if(mi) d[x]=-1;
        return flow;
    }
    
    bool DINIC(int x){
        int ans=0;
        while(bfs()){
            ans+=dfs(s,INF);
        }
        if(ans>=n-k+1) return 1;
        return 0;
    }
    
    bool check(int x){
        memset(e,0,sizeof(e));
        memset(head,0,sizeof(head));
        cnt=1;
        for(int i=1;i<=n;i++) add(s,i,1);
        for(int j=1;j<=m;j++) add(j+n,t,1);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(a[i][j]<=x) add(i,j+n,INF);
            }
        }
        if(DINIC(x)) return 1;
        return 0;
    }
    
    int main(){
        //freopen("matrix.in","r",stdin);
        //freopen("matrix.out","w",stdout);
        n=read();m=read();k=read();
        s=m+n+1;t=s+1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                a[i][j]=read();
                maxn=max(maxn,a[i][j]);
            }
        }
        int l=1,r=maxn;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid)){
                r=mid-1;ans=mid;
            }
            else l=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Mac上的USB存储设备使用痕迹在新版操作系统有所变化
    Beware of the encrypted VM
    A barrier for Mobile Forensics
    Second Space could let suspect play two different roles easily
    Take advantage of Checkra1n to Jailbreak iDevice for App analysis
    Find out "Who" and "Where"
    Where is the clone one and how to extract it?
    Downgrade extraction on phones running Android 7/8/9
    高版本安卓手机的取证未来
    How to extract WeChat chat messages from a smartphone running Android 7.x or above
  • 原文地址:https://www.cnblogs.com/zsq259/p/10561805.html
Copyright © 2011-2022 走看看