# [BZOJ2162]男生女生（二分图带权独立集+dp）

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define erp(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int inf = 0x3f3f3f3f;
const int mo = 19921228;
const int MAXN = 105;
void up(int&a, int b) { a+=b;if(a>=mo)a-=mo; }

int c[2505][2505], f[55][55];
void makecomb()
{
c[0][0] = 1;
rep(i, 1, 2500)
{
c[i][0]=c[i][i]=1;
rep(j, 1, i) c[i][j] = (c[i-1][j-1]+c[i-1][j])%mo;
}
}
int C(int n, int r)
{
if (r>n||r<0) return 0;
return c[n][r];
}

bool inS[105], inT[105];
struct Ed{ int to, nxt, c; };
struct FlowNet
{
Ed e[100000];
bool vis[MAXN];
int ec, adj[MAXN], d[MAXN], vd[MAXN];
int S, T, flow, vn;
void init(int n, int s, int t)
{
rep(i, 1, n) adj[i] = -1;
vn = n, S = s, T = t;
}
void adde(int a, int b, int c)
{
e[ec].to = b;
e[ec].c = c;
e[ec].to = a;
e[ec].c = 0;
}
int aug(int u, int augco)
{
if (u==T) return augco;
int delta, augc = augco, mind = vn-1;
for (int i = adj[u], v; ~i; i=e[i].nxt)
{
v = e[i].to;
if (e[i].c<=0) continue;
if (d[u] == d[v]+1)
{
delta = aug(v, min(augc, e[i].c));
e[i].c -= delta, e[i^1].c += delta;
augc -= delta;
if (d[S]>=vn) return augco-augc;
if (!augc) break;
}
mind = min(mind, d[v]);
}
if (augc==augco)
{
if (!--vd[d[u]]) d[S] = vn;
++vd[d[u] = mind+1];
}
return augco - augc;
}
int sap()
{
vd[0] = vn;
flow = 0;
while (d[S]<vn) flow+=aug(S, inf);
return flow;
}
void dfsS(int u)
{
vis[u] = inS[u] = 1;
for (int i=adj[u]; ~i; i=e[i].nxt)
if (e[i].c>0&&!vis[e[i].to]) dfsS(e[i].to);
}
void dfsT(int u)
{
vis[u] = inT[u] = 1;
for (int i=adj[u]; ~i; i=e[i].nxt)
if (e[i^1].c>0&&!vis[e[i].to]) dfsT(e[i].to);
}
void getcut()
{
memset(vis,0,sizeof vis); dfsS(S);
memset(vis, 0, sizeof vis); dfsT(T);
}
} G;

int N, K, M, n, m;
bool love[55][55];
void solve()
{
makecomb();
printf("%d %d\n", n, m);
rep(a, 1, n) rep(b, 1, m)
{
f[a][b] = C(a*b, K);
rep(i, 1, a) rep(j, 1, b) if(i!=a||j!=b)
{
f[a][b] += mo-1ll*f[i][j]*C(a,i)%mo*C(b,j)%mo;
f[a][b] %= mo;
}
}
printf("%d\n", f[n][m]);
}

int main()
{
freopen("boygirl.in","r",stdin);
freopen("boygirl.out","w",stdout);
int a, b;
scanf("%d%d%d", &N, &K, &M);
G.init(2*N+2, 2*N+1, 2*N+2);
rep(i, 1, M) scanf("%d%d",&a,&b), love[a][b]=1;
rep(i, 1, N) G.adde(G.S, i, 999), G.adde(N+i, G.T, 998);
rep(i, 1, N) rep(j, 1, N) if (!love[i][j]) G.adde(i, N+j, inf);
G.sap();
G.getcut();
rep(i, 1, N) if (inS[i]) ++n;
rep(i, 1, N) if (inT[N+i]) ++m;
solve();
return 0;
}


• 本文已收录于以下专栏：

## 二分图带权最大独立集

• u012550356
• 2015年09月01日 12:04
• 563

## 二分图带权最大独立集 网络流解决 hdu 1569

• hnust_xiehonghao
• 2013年08月26日 13:48
• 2469

## 树的最大独立集——树形dp

• qq_33850438
• 2016年02月22日 02:22
• 1638

## 【NOIP2017模拟赛】二分图+状态压缩DP Graph（好题）

• C20190101ZJX
• 2017年11月09日 17:12
• 102

## 二分图的最大点权独立集和最小点权覆盖集

• zhjchengfeng5
• 2012年09月08日 18:13
• 794

## 二分图 最小覆盖数 = 最大匹配数、最大独立集 = 总数-最小覆盖集 证明 hdu 1068

• Techmonster
• 2015年11月24日 13:19
• 2178

## 二分图带权匹配问题

• wsniyufang
• 2011年09月08日 11:39
• 5882

## 带权二分图的最佳匹配（KM算法）

• x_y_q_
• 2016年07月16日 23:17
• 3645

## 【算法小总结】二分图的最大独立集

• u013517797
• 2014年08月14日 21:19
• 1251

## HDU 1569 - 方格取数(2) 二分图最大点权独立集(构图最大流解)

• kk303
• 2013年08月24日 18:31
• 1650

举报原因： 您举报文章：[BZOJ2162]男生女生（二分图带权独立集+dp） 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)