BZOJ4443: [Scoi2015]小凸玩矩阵 解题报告

来源:互联网 发布:slice方法js实现分页 编辑:程序博客网 时间:2024/05/27 06:14

日常吐槽,可跳过这部分

这道题第一眼就觉得要二分一下答案,然后…然后我发现我不会……..冷静下来,想了一会,感觉可以二分后可以贪心一下,然后就欢快的打了起来
打完过了样例,然后WA了(不对呀我这么正确正解怎么会WA呢)
打了个对拍死活拍不出来,好吧我弱我看题解唉呀我怎么没想到二分匹配…….(但我真的觉得我原来的做法没错的)
没救了



吐槽结束下面是题解

二分一下第k大,然后二分匹配一下,不大于二分的第k大的都将这列和这行连边,
如果最大匹配数nk+1就可行



code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<ctime>#include<cmath>#include<string>#include<vector>#include<string>#include<cstdio>#include<cstring>#include<climits>#include<cstdlib>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;const int maxn = 270;int mat[maxn][maxn],d[maxn*maxn];int match[maxn];bool v[maxn];int n,m,k,num;struct edge{    int y,next;}a[maxn*maxn]; int len,first[maxn];void insert(int x,int y){    len++;    a[len].y=y;    a[len].next=first[x];first[x]=len;}bool find_( int x ){    if( v[x] ) return false;    v[x] = true;    for( int k=first[x];k;k=a[k].next )    {        int y=a[k].y;        if(!match[y]||find_(match[y]))        {            match[y]=x;            return true;        }    }    return false;}bool judge(int now){    memset(first,0,sizeof first); len=0;    memset(match,0,sizeof match);    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            if(mat[i][j]<=now) insert(i,j);    int ret=0;    for(int i=1;i<=n;i++)    {        memset(v,false,sizeof v);        if( find_(i) ) ret++;    }    return ret>n-k;}int solve(){    int l=1,r=num;    while(l<=r)    {        int mid=(l+r)>>1;        if(judge(d[mid])) r=mid-1;        else l=mid+1;    }    return r+1;}int main(){    //freopen("tmp.in","r",stdin);    //freopen("tmp.out","w",stdout);    scanf("%d%d%d",&n,&m,&k);    num=0;    for( int i=1;i<=n;i++ )        for( int j=1;j<=m;j++ )        {            scanf("%d",&mat[i][j]);            d[++num]=mat[i][j];        }    sort(d+1,d+num+1);    printf("%d\n",d[solve()]);    return 0;}
0 0
原创粉丝点击