
二分答案,每次将小于等于当前值的边加入二分图中,看最大流能否大于等于n-k+1,反着来是不行的,因为如果最大流大于k-1,不代表只能向上二分,可以不取最大流。
#include <cstdio>//输入字符串必需
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long int
const int maxn=90001;
struct node
{
string s;
ll len,x,y;
}p[maxn];
ll vis[301][301],g[301],d[301];
ll n,k,top=0,ans;
bool cmp(node a,node b)//字符串排序
{
if(a.len==b.len)
return a.s<b.s;
return a.len<b.len;
}
bool dfs(ll x)
{
ll i;
for(i=1;i<=n;i++)
{
if(vis[x][i]&&!d[i])
{
d[i]=1;//这里改变d
if(!g[i]||dfs(g[i]))
{
g[i]=x;
return 1;
}
}
}
return 0;
}
bool check(ll x)
{
ll i;
for(i=1;i<=top;i++)
{
if(p[x].len==p[i].len)
{
if(p[x].s>=p[i].s)
vis[p[i].x][p[i].y]=1;
else
vis[p[i].x][p[i].y]=0;//必需清0
}
else if(p[x].len>p[i].len)
vis[p[i].x][p[i].y]=1;
else
vis[p[i].x][p[i].y]=0;
}
memset(g,0,sizeof(g));
for(i=1;i<=n;i++)
{
memset(d,0,sizeof(d));
dfs(i);
}
ll sum=0;
for(i=1;i<=n;i++)
{
if(g[i])
sum++;
}
if(sum>=n-k+1)//(最大流的性质)至少是第k大,所以向下二分
return 1;
return 0;
}
int main()
{
scanf("%lld%lld",&n,&k);
ll i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
cin>>p[++top].s;//字符串cin
p[top].len=(p[top].s).size();//字符串长度
p[top].x=i,p[top].y=j;
}
}
sort(p+1,p+top+1,cmp);
ll l=1,r=top;//离散化
while(l<=r)
{
ll mid=(l+r)/2;
if(check(mid))
{
ans=mid;
r=mid-1;
}
else
l=mid+1;
}
cout<<p[ans].s<<endl;//字符串cout
return 0;
}
浙公网安备 33010602011771号