HDU3277MarriageMatchIII
题意:和上一篇差不多,就是多了每个女孩可以另外选任意k个不喜欢的;
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#define LL long long
#define Inf 0x7fffffff
using namespace std;
int fa[500];
int dis[1010],cur[1010],gap[1010],head[1010],x[62510],y[62510],pre[1010];
int g[255][255];
int len,n,m,k,f,st,ed;
struct node
{
int v,next,w;
}t[5000010];
void add(int x,int y,int w)
{
t[len].next=head[x];
t[len].v=y;
t[len].w=w;
head[x]=len++;
}
int Isap()
{
int flow=0,d=Inf,i,flag=0,u;
for (i=0; i<=ed; i++)
{
dis[i]=gap[i]=0;
cur[i]=head[i];
}
gap[0]=ed+1;
u=pre[st]=st;
while (dis[st]<ed+1)
{
flag=false;
//printf("%d %d\n",u,dis[u]);
for (int &j=cur[u]; j!=-1; j=t[j].next)
{
int v=t[j].v;
if (t[j].w>0 && dis[v]+1==dis[u])
{//printf("dfa");
d=min(d,t[j].w);
flag=true;
pre[v]=u;
u=v;
//printf("%d ==",u);
if (u==ed)
{
flow+=d;
while (u!=st)
{
u=pre[u];
t[cur[u]].w-=d;
t[cur[u]^1].w+=d;
}
d=Inf;
}
break;
}
}
if (flag) continue ;
int minh=ed+1;
for (int j=head[u]; j!=-1; j=t[j].next)//wrong
{
int v=t[j].v;
if (t[j].w>0 && minh>dis[v])//wrong
{
minh=dis[v];
cur[u]=j;
}
}
--gap[dis[u]];
if (gap[dis[u]]==0) break;
dis[u]=minh+1;
gap[dis[u]]++;
u=pre[u];
}
return flow;
}
bool check(int p)
{
int i,j;
if (p==0) return true;
memset(head,-1,sizeof(head));
len=0;
for (i=1; i<=n; i++)
{
add(st,i,p);
add(i,st,0);
add(i,i+n,k);
add(i+n,i,0);
add(2*n+i,ed,p);
add(ed,2*n+i,0);
}
for (i=1; i<=n; i++)
{
for (j=1; j<=n; j++)
if (g[i][j])
{
add(i,2*n+j,1);
add(2*n+j,i,0);
}
else
{
add(n+i,2*n+j,1);
add(2*n+j,n+i,0);
}
}
int ans=Isap();
if (ans==n*p) return true;
else return false;
}
void getans()
{
int l=0,r=n;
int i,j;
st=0,ed=3*n+1;
while (r-l>=2)
{
int mid=(l+r)/2;
if (check(mid)) l=mid;
else r=mid;
}
for (i=r; i>=l; i--)
if (check(i))
{
printf("%d\n",i);
break;
}
}
int find(int x)
{
if (fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}
void join(int a,int b)
{
int x=find(a),y=find(b);
if (x==y) return ;
if (x<y) fa[y]=x;
else fa[x]=y;
}
int main()
{
int i,j,T;
int a,b;
freopen("1.in","r",stdin);
scanf("%d",&T);
while (T--)
{
memset(g,0,sizeof(g));
scanf("%d%d%d%d",&n,&m,&k,&f);
for (i=1; i<=n; i++) fa[i]=i;
for (i=1; i<=m; i++)
{
scanf("%d%d",&x[i],&y[i]);//wrong yue jie
}
for (i=1; i<=f; i++)
{
scanf("%d%d",&a,&b);
join(a,b);
}
for (i=1; i<=m; i++)
g[find(x[i])][y[i]]=1;
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
if (g[find(i)][j]) g[i][j]=1;
getans();
}
return 0;
}