HDU 6151 Party (二分图)
来源:互联网 发布:php pack 函数 java 编辑:程序博客网 时间:2024/06/05 04:29
Problem
被含糊的题意坑到了,竟然都没想到是原题(变体? CERC 2016 B)
派对预选受邀人可视作二分图,n 个男孩与 m 个女孩分属两个不相交集合。每人都有一个标记
有 q 个询问,每个询问给定一个 g ,问在所有标号为 g 的倍数的点组成的子图中,有多少中取点方式,使得选择的点至少是一条边的某个端点,同时不存在任意两条边共享一个端点。
Idea
霍尔定理:二分图 G 中的两不相交点集 X, Y ,X={X1, X2, X3, …, Xn} , Y = {Y1, Y2, Y3, …, Ym} ,G 中有一组无公共点的边,一端恰好为组成 X 的点的充要条件为: X 中的任意 k 个点至少与 Y 中的 k 个点相邻。
记录输入的所有信息,mask_right
表示与右部点 i 相邻的所有左部点的状压状态, mask_left
类似。
问题可以视作为:
ansLeft = 有多少个不同的左部点集合 X ,使得 X 中的任意 k 个点至少与右部中 k 个点相邻。
ansRight = 有多少个不同的右部点集合 Y ,使得 Y 中的任意 k 个点至少与左部中 k 个点相邻。
ans = ansLeft * ansRight - 1 (ansLeft 和 ansRight 中都包含空集,答案不允许空集)。
Code
// 部分代码优化来自于 CERC-2016 B 的官方标程// 虽然还是在 HDOJ 上跑了 1248 ms .#include<bits/stdc++.h>using namespace std;const int N = 20, M = 20;int T, n, m, q, g;bool A[N], B[M];int a[N], b[M];char grid[N][M];int mask_right[M];int mask_left[N];int solve(int* mask, int n, int m, bool *A, bool *B) { static int can[1<<N]; int ans = 0; int STD = 0; for(int i=0;i<n;i++) if(A[i] == true) STD |= (1<<i); can[0] = true; for(int state=0;state<(1<<n);state++) { if((STD | state) != STD) continue; int pcnt = 0; can[state] = true; for(int i=0;i<n;i++) if(A[i] && (state & (1<<i))) can[state] &= can[state-(1<<i)]; for(int i=0;i<n;i++) if(A[i] && (state & (1<<i))) ++pcnt; int c = 0; for(int j=0;j<m;j++) if(B[j] && (mask[j] & state)) ++c; if(c < pcnt) can[state] = false; if(can[state]) ans++; } return ans;} int main(){ scanf("%d", &T); for(int ica=1;ica<=T && scanf("%d %d %d", &n, &m, &q)!=EOF;ica++) { memset(mask_left, 0, sizeof(mask_left)); memset(mask_right, 0, sizeof(mask_right)); for(int i=0;i<n;i++) for(int j=0;j<m;j++) { scanf(" %c", &grid[i][j]); grid[i][j] -= '0'; if(grid[i][j]) mask_right[j] |= 1<<i, mask_left[i] |= 1<<j; } for(int i=0;i<n;i++) scanf("%d", &a[i]); for(int j=0;j<m;j++) scanf("%d", &b[j]); printf("Case #%d: ", ica); while(q-- && scanf("%d", &g)) { for(int i=0;i<n;i++) if(a[i] % g == 0) A[i] = 1; else A[i] = 0; for(int j=0;j<m;j++) if(b[j] % g == 0) B[j] = 1; else B[j] = 0; long long ansLeft = solve(mask_right, n, m, A, B); long long ansRight = solve(mask_left, m, n, B, A); printf("%lld%c", ansLeft * ansRight - 1, q?' ':'\n'); } }}
阅读全文
0 0
- HDU 6151 Party (二分图)
- HDU 4355 Party All the Time(三分|二分)
- UVALive 4244 Party Party Party(HDU 2779 && Sicily 1663)
- POJ 3663 Costume Party (二分查找)
- 二分图(Arpa’s overnight party and Mehrdad’s silent entering,cf 741C)
- Codeforces742E-Arpa’s overnight party and Mehrdad’s silent entering(构造+二分图染色)
- hdu 3118 (二分图)
- HDU 1045(二分图)
- hdu 2063 (二分图)
- hdu 3062 Party(2-sat入门)
- hdu(1520) Anniversary party(树形dp)
- HDU 1520 Anniversary party (树状dp)
- hdu 1520 Anniversary party(树dp)
- [hdu 3062] Party(2-sat入门)
- hdu 1520 Anniversary party(树形dp)
- hdu 3506 monkey party(环形dp)
- HDU-#3062 Party(2-SAT)
- HDU 1520 - Anniversary party(树形DP)
- 懒汉式的线程安全
- HDU1330-Nearest Common Ancestors
- 查看 Linux 系统使用量基本命令
- 【面试】int、integer、String
- ThinkPHP跨控制器调用方法
- HDU 6151 Party (二分图)
- 17暑假多校联赛7.10 HDU 6129 Just do it
- spring mvc 知识点
- 《C++ Primer》第五版课后习题解答_第一章(2)(12-25)
- C#基础-004接收控制台传入的数据
- 如何写好技术简历:实例、模板及工具
- 离线环境下构建 sbt 项目
- java虚拟机运行时内存分配
- MFC中SetTimer定时不准确?试试用多媒体定时器吧