您的位置:首页 > 其它

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

2016-10-02 22:29 239 查看

日常吐槽,可跳过这部分

这道题第一眼就觉得要二分一下答案,然后…然后我发现我不会……..冷静下来,想了一会,感觉可以二分后可以贪心一下,然后就欢快的打了起来

打完过了样例,然后WA了(不对呀我这么正确的 正解怎么会WA呢)

打了个对拍死活拍不出来,好吧我弱我看题解唉呀我怎么没想到二分匹配…….(但我真的觉得我原来的做法没错的)

没救了

吐槽结束下面是题解

二分一下第k大,然后二分匹配一下,不大于二分的第k大的都将这列和这行连边,

如果最大匹配数≥n−k+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 long
using 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: