zoukankan      html  css  js  c++  java
  • loj #2006. 「SCOI2015」小凸玩矩阵

    #2006. 「SCOI2015」小凸玩矩阵

     

    题目描述

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

    输入格式

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

    输出格式

    输出选出来的 N NN 个数中第 K KK 大的数字的最小值。

    样例

    样例输入

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

    样例输出

    3

    数据范围与提示

    1≤K≤N≤M≤250,1≤Ai,j≤109 1 leq K leq N leq M leq 250, 1 leq A_{i, j} leq 10 ^ 91KNM250,1Ai,j​​109​​

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,m,k,map[260][260],a[260],b[260],ans=0x3f3f3f3f;
    bool vis[260];
    int cmp(int x,int y){return x>y;}
    void check(){
        for(int i=1;i<=n;i++)b[i]=a[i];
        sort(b+1,b+n+1,cmp);
        ans=min(ans,b[k]);
    }
    void dfs(int now){
        if(now==n+1){
            check();
            return;
        }
        for(int i=1;i<=m;i++){
            if(!vis[i]){
                vis[i]=1;
                a[now]=map[now][i];
                dfs(now+1);
                vis[i]=0;
            }
        }
    }
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        int x;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&map[i][j]);
        dfs(1);
        printf("%d",ans);
    }
    20分 暴力
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define maxn 510
    #define INF 1000000000
    using namespace std;
    int S,T,num=1,head[maxn],n,m,k,dis[maxn],a[maxn][maxn];
    struct node{int to,pre,v;}e[maxn*maxn];
    void Insert(int from,int to,int v){
        e[++num].to=to;e[num].v=v;e[num].pre=head[from];head[from]=num;
        e[++num].to=from;e[num].v=0;e[num].pre=head[to];head[to]=num;
    }
    int dinic(int x,int flow){
        if(x==T||flow==0)return flow;
        int rest=flow;
        for(int i=head[x];i;i=e[i].pre){
            int to=e[i].to;
            if(dis[to]==dis[x]+1&&e[i].v>0){
                int delta=dinic(to,min(e[i].v,rest));
                e[i].v-=delta;
                e[i^1].v+=delta;
                rest-=delta;
            }
        }
        return flow-rest;
    }
    bool spfa(){
        memset(dis,-1,sizeof(dis));
        queue<int>q;q.push(S);dis[S]=0;
        while(!q.empty()){
            int now=q.front();q.pop();
            for(int i=head[now];i;i=e[i].pre){
                int to=e[i].to;
                if(dis[to]==-1&&e[i].v>0){
                    dis[to]=dis[now]+1;
                    if(to==T)return 1;
                    q.push(to);
                }
            }
        }
        return dis[T]!=-1;
    }
    int work(){
        int res=0;
        while(spfa()){
            res+=dinic(S,INF);
        }
        return res;
    }
    bool check(int x){
        memset(head,0,sizeof(head));num=1;
        for(int i=1;i<=n;i++)Insert(S,i,1);
        for(int i=1;i<=m;i++)Insert(i+n,T,1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(a[i][j]<=x)Insert(i,j+n,1);
        int res=work();
        if(res>=n-k+1)return 1;
        return 0;
    }
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        S=0;T=n+m+1;
        int mx=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                scanf("%d",&a[i][j]);
                mx=max(mx,a[i][j]);
            }
        int l=0,r=mx,ans=0;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid))r=mid-1,ans=mid;
            else l=mid+1;
        }
        printf("%d",ans);
    }
    100分 二分答案+网络流
  • 相关阅读:
    UVA1452|LA4727-----Jump------经典的约瑟夫公式的变形(DP)
    ORM框架Hibernate (四) 一对一单向、双向关联映射
    heaters
    对SIGQUIT的实验 & Java dump
    【Todo】单例模式各种实现方式及并发安全
    【转载】Spark系列之运行原理和架构
    git本地文件回滚操作
    Java异常与运行时异常,以及与线程的关系
    Callable与Future、FutureTask的学习 & ExecutorServer 与 CompletionService 学习 & Java异常处理-重要
    Linux系统负载排查
  • 原文地址:https://www.cnblogs.com/thmyl/p/8867256.html
Copyright © 2011-2022 走看看