JZOJ5000. 保镖
来源:互联网 发布:中俄翻译软件 编辑:程序博客网 时间:2024/04/28 13:18
题目大意
5000留念
现在有一副若干条边的二分图,左边有
- 选出的点权和大于等于限制t
- 并且可以从图中选出若干条边,使得二分图中每个点最多被一条边覆盖,而选出的点要恰好被一条边覆盖。
求有多少个满足条件的子图。
Data Constraint
题解
这题要用到霍尔定理。
Hall定理
简单讲一下我个人的理解。
对于一个二分图具备完备匹配的充要条件是对于左边点的每一个子集,和子集内的点相连的点集大小大于等于子集大小。
假如说只选出一遍的点的子集,我们显然可以Hall定理判断。实际上两边如果都满足,那么这个结论还是成立的。
所以我们只需要分别找出两边合法的方案,然后two pointers扫一下就解决了。
时间复杂度:
SRC
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#include<vector>using namespace std ;#define N 40 + 10#define M 2000000 + 10typedef long long ll ;bool f[2][M] ;ll Rec1[M] , Rec2[M] ;int W[N] , G[2][N] , Num[M] ;int n , on , m , T , Size ;ll ans ;void link1( int u , int v ) { G[0][u] |= 1 << (v - 1) ;}void link2( int u , int v ) { G[1][u] |= 1 << (v - 1) ;}int Count( int s ) { int ret = 0 ; while ( s ) { ret ++ ; s -= s & (-s) ; } return ret ;}void Solve( int n , int t ) { for (int s = 0 ; s < (1 << n) ; s ++ ) { f[t][s] = 1 ; int st = 0 ; ll sum = 0 ; for (int i = 1 ; i <= n ; i ++ ) { if ( (s >> (i - 1)) & 1 ) { int _s = s ^ (1 << (i - 1)) ; if ( !f[t][_s] ) { f[t][s] = 0 ; break ; } st |= G[t][i] ; sum += W[t*on+i] ; } } if ( Num[st] < Num[s] ) f[t][s] = 0 ; if ( f[t][s] ) { if ( t == 0 ) Rec1[++Rec1[0]] = sum ; else Rec2[++Rec2[0]] = sum ; } }}int main() { freopen( "guard.in" , "r" , stdin ) ; freopen( "guard.out" , "w" , stdout ) ; scanf( "%d%d" , &n , &m ) ; for (int i = 1 ; i <= n ; i ++ ) { scanf( "\n" ) ; for (int j = 1 ; j <= m ; j ++ ) { char c ; scanf( "%c" , &c ) ; if ( c == '1' ) link1( i , j ) , link2( j , i ) ; } } for (int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &W[i] ) ; for (int i = 1 ; i <= m ; i ++ ) scanf( "%d" , &W[n+i] ) ; scanf( "%d" , &T ) ; for (int s = 0 ; s < (1 << max(n,m)) ; s ++ ) Num[s] = Count(s) ; on = n ; Solve( n , 0 ) ; Solve( m , 1 ) ; sort( Rec1 + 1 , Rec1 + Rec1[0] + 1 ) ; sort( Rec2 + 1 , Rec2 + Rec2[0] + 1 ) ; int j = Rec2[0] + 1 ; for (int i = 1 ; i <= Rec1[0] ; i ++ ) { while ( j > 1 && Rec2[j-1] + Rec1[i] >= T ) j -- ; if ( Rec2[j] + Rec1[i] >= T ) ans += Rec2[0] - j + 1 ; } printf( "%lld\n" , ans ) ; return 0 ;}
以上.
1 0
- JZOJ5000. 保镖
- 保镖
- 流氓保镖
- 海盗、保镖
- 大保镖
- 保镖排队
- [CERC2016][JZOJ5000]Bipartite Blanket 结论
- 中南海保镖--李连杰 主演
- 【动态规划】保镖排队
- 【树形DP】保镖排队
- QA与“如此保镖”
- 破解超级保镖的密码
- 隐私保镖 v0.20 bt
- bodyguard 保镖 护卫队 有关能力
- 单身女性租房 验房时要叫上“保镖”?
- 揭秘北京奥运会上的中国保镖[转贴]
- 通用网址拍卖“中国少林功夫”“中国保镖”
- “道德”,究竟是保镖还是杀手?
- 【程序21】 题目:求1+2!+3!+...+20!的和
- [蓝桥杯] C++ CH08 01
- GYM 100712 L.Alternating Strings II(dp+线段树)
- HTML中详情和概要标签
- 可动态部署的web应用
- JZOJ5000. 保镖
- Java多线程笔记
- http、tcp/ip、socket
- STL算法reverse,reverse_copy
- JS获取项目路径
- 递归算法学习
- Android中自定义圆形选择器(可用于数字选择,评价选择等)
- CTF连接整理【零碎资料收集】
- 事务的基本概念和事务的性质