[BZOJ2162]男生女生(二分图带权独立集+dp)
来源:互联网 发布:关于php的网站 编辑:程序博客网 时间:2024/05/29 19:23
题意:懒得写了,比较麻烦。
强行嵌套的题真没意思。。
开始我看见数据范围n=50,第一问求什么完全子图,我以为是个搜索减枝,然后第二问那个dp我想了想,列了几个方程发现不是很对,然后又没有部分分,我就弃疗了。。
其实想一想应该是想得出来的,主要是考试的时候写了第二题的很麻烦的做法,被折腾得没精力了,就没怎么想。。第一问其实很简单,二分图完全子图是P类的。我们求出这个二分图的补图,补图中的边就表示这两个点不能被同时选,于是就是最大点独立集了。由于要选出尽量多的男生,我们用最小割来做带权独立集即可,在S割中的男生和在T割中的女生都要选。
然后就是个DP。设f[a,b]表示a个男生b个女生中连k条边的方案(注意k是常数),可以看做在a*b的矩阵里放k个点,使得每行每列都有点。f[a,b]=C(a*b,k)-Σf[i,j]*C(a,i)*C(b,j)。
#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].nxt = adj[a];adj[a] = ec++;e[ec].to = a;e[ec].c = 0;e[ec].nxt = adj[b];adj[b] = ec++;}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;}
0 0
- [BZOJ2162]男生女生(二分图带权独立集+dp)
- Bzoj2162:男生女生:网络流+容斥
- 二分图带权最大独立集
- 二分图(最大独立集)
- hdu3829(二分图,最大独立集)
- hdu1151(二分图最大独立集)
- codevs1922(二分图最大独立集)
- poj3692(二分图最大独立集)
- poj2724(*二分图最大独立集)
- Codeforces 808F Card Game(和是素数二分图建图+二分图带权最大独立集)
- hdu1565 方格取数 最大流(二分图极大点权独立集) 或状态压缩dp
- NKOJ 3500 独立集(dp)
- 二分图最大独立集
- 二分图最大独立集
- 二分图最大独立集
- HDU1068 二分匹配 独立集
- 二分图带权最大独立集 网络流解决 hdu 1569
- HDU 1569 二分图带权最大独立集 最小割
- 学习笔记之自适应布局
- java- 分布式- 一致性哈希算法(2)
- 熟悉 CMake (三)—— 配置 opencv3
- LightOJ 1010
- JavaScript学习笔记06
- [BZOJ2162]男生女生(二分图带权独立集+dp)
- Android 6.0 Changes(新特性)
- 一致性哈希算法
- 工程师需要哪些软实力
- 图像的膨胀处理
- APP开发实战41-对称加密介绍
- How to develop a person
- Spring ApplicationContext
- 输入一个三位正整数,逆序输出!