loj #2006. 「SCOI2015」小凸玩矩阵

 

#2006. 「SCOI2015」小凸玩矩阵

 

题目描述

小凸和小方是好朋友,小方给小凸一个 N×M N \times 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分 二分答案+网络流

 

posted @ 2018-04-17 15:57  Echo宝贝儿  阅读(301)  评论(2编辑  收藏  举报