zoukankan      html  css  js  c++  java
  • BZOJ4443: [Scoi2015]小凸玩矩阵

    Description

    小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少。
     

    Input

    第一行给出三个整数N,M,K
    接下来N行,每行M个数字,用来描述这个矩阵
     

    Output

    如题 
     

    Sample Input

    3 4 2
    1 5 6 6
    8 3 4 3
    6 8 6 3

    Sample Output

    3

    HINT

    1<=K<=N<=M<=250,1<=矩阵元素<=10^9

     
    二分答案x,然后“存在方案使得第K大的数<=x”等价于“存在方案选n-k+1个数<=x”。
    那么二分图匹配即可。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=510;
    const int maxm=200010;
    const int inf=1e9;
    struct ISAP{
        struct tedge{int x,y,w,next;}adj[maxm];int ms,fch[maxn];
        int d[maxn],s[maxn],cur[maxn],gap[maxn],n,top;
        void init(int n){
            this->n=n;ms=0;top=0;
            memset(d,-1,sizeof(d));
            memset(fch,-1,sizeof(fch));
            return;
        }
        void AddEdge(int u,int v,int w){
            adj[ms]=(tedge){u,v,w,fch[u]};fch[u]=ms++;
            adj[ms]=(tedge){v,u,0,fch[v]};fch[v]=ms++;
            return;
        }
        void bfs(){
            queue<int>Q;Q.push(n);d[n]=0;
            while(!Q.empty()){
                int u=Q.front();Q.pop();
                for(int i=fch[u];i!=-1;i=adj[i].next){
                    int v=adj[i].y;
                    if(d[v]==-1) d[v]=d[u]+1,Q.push(v);
                }
            } return;
        }
        int solve(int S,int T){
            n=T;bfs();int k=S,i,flow=0;
            for(i=0;i<=n;i++) cur[i]=fch[i],gap[d[i]]++;
            while(d[S]<n){
                if(k==n){
                    int mi=inf,pos;
                    for(i=0;i<top;i++) if(adj[s[i]].w<mi) mi=adj[s[i]].w,pos=i;
                    for(i=0;i<top;i++) adj[s[i]].w-=mi,adj[s[i]^1].w+=mi;
                    flow+=mi;top=pos;k=adj[s[top]].x;
                }
                for(i=cur[k];i!=-1;i=adj[i].next){
                    int v=adj[i].y;
                    if(adj[i].w&&d[k]==d[v]+1){cur[k]=i;k=v;s[top++]=i;break;}
                }
                if(i==-1){
                    int lim=n;
                    for(i=fch[k];i!=-1;i=adj[i].next){
                        int v=adj[i].y;
                        if(adj[i].w&&d[v]<lim) lim=d[v],cur[k]=i;
                    } if(--gap[d[k]]==0) break;
                    d[k]=lim+1;gap[d[k]]++;
                    if(k!=S) k=adj[s[--top]].x;
                }
            } return flow;
        }
    }sol;
    int n,m,k,val[maxn][maxn];
    int check(int x) {
        int S=n+m+1,T=n+m+2;sol.init(T);
        rep(i,1,n) sol.AddEdge(S,i,1);
        rep(i,1,m) sol.AddEdge(i+n,T,1);
        rep(i,1,n) rep(j,1,m) if(val[i][j]<=x) sol.AddEdge(i,j+n,1);
        return sol.solve(S,T)>=n-k+1;
    }
    int main() {
        n=read();m=read();k=read();
        int l=inf,r=-inf,mid;
        rep(i,1,n) rep(j,1,m) {
            val[i][j]=read();
            l=min(l,val[i][j]);
            r=max(r,val[i][j]);
        }
        while(l<r) if(check(mid=l+r>>1)) r=mid; else l=mid+1;
        printf("%d
    ",l);
        return 0;
    }
    View Code
  • 相关阅读:
    iOS各种证书
    Error No matching provisioning profiles found
    iOS 一个开发者账号 多台Mac 共用
    外中断(学习汇编)
    端口(学习汇编)
    8086CPU寄存器
    int指令(学习汇编)
    内中断(学习汇编)
    标志寄存器(学习汇编)
    CALL和RET指令(学习汇编)
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5311731.html
Copyright © 2011-2022 走看看