二分答案,每次将小于等于当前值的边加入二分图中,看最大流能否大于等于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; }