HDU3605 Escape(最大流判满流 + 状压)
【题意】:
有N个人,M个星球,给N*M矩阵,(i, j)为1代表i可以到j星球,0代表不能,问是否能把所有人转移走。
【思路】:
N的范围为1e6,如果让每个人与星球连边一定TLE,再根据矩阵每一行只有0,1可以进行状压,把相同状态idx的人合并到数组siz[idx],
在扫描状态,与符合条件的星球连边。
【建图】:
超级源点sp -> idx 边权siz[idx]
idx -> M 边权inf
M -> 超级汇点tp 边权为容量
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; const int maxm = 10 + 5; const int inf = 0x3f3f3f3f; int n, m, d[maxn+maxm], siz[maxn]; int head[maxn+maxm], tot, maxflow; int sp, tp; struct edge{ int to, w, next; } ed[(maxn*maxm+maxn+maxm)<<1]; inline void init(){ memset( head ,-1, sizeof(head) ); memset( siz, 0, sizeof(siz) ); tot = 1; } inline void add( int u, int v, int w ){ ed[++tot].to = v; ed[tot].w = w; ed[tot].next = head[u]; head[u] = tot; ed[++tot].to = u; ed[tot].w = 0; ed[tot].next = head[v]; head[v] = tot; } inline bool bfs(){ memset( d, 0, sizeof(d) ); queue<int> q; d[sp] = 1; q.push(sp); while( !q.empty() ){ int x = q.front(); q.pop(); for( int i=head[x]; i!=-1; i=ed[i].next ){ int y = ed[i].to; if( ed[i].w && !d[y] ){ d[y] = d[x] + 1; q.push(y); if( y==tp ) return 1; } } } return 0; } inline int dfs( int x, int flow ){ if( x==tp ) return flow; int res = flow, k; for( int i=head[x]; i!=-1 && res; i=ed[i].next ){ int y = ed[i].to; if( ed[i].w && d[y]==d[x]+1 ){ k = dfs( y, min( ed[i].w, res ) ); if(!k) d[y] = 0; ed[i].w -= k; ed[i^1].w += k; res -= k; } } return flow-res; } inline void dinic(){ int flow = maxflow = 0; while( bfs() ) while( flow=dfs(sp, inf) ) maxflow += flow; } int main(){ // freopen("in.txt", "r", stdin); while( ~scanf("%d%d", &n, &m) ){ init(); int l = inf, r = -inf; for( int i=1; i<=n; i++ ){ int sum = 0; for( int j=1; j<=m; j++ ){ int tmp; scanf("%d", &tmp); sum <<= 1; sum += tmp; } siz[sum] ++; l = min( l, sum ); r = max( r, sum ); } sp = 0; tp = r+m+1; for( int i=1; i<=m; i++ ){ int cont; scanf("%d", &cont); add( i+r, tp, cont ); } for( int i=l; i<=r; i++ ) if( siz[i] ){ int pos = 0; while( pos<m ){ if( i&(1<<pos) ) add( i, m-pos+r, inf ); pos ++; } add( sp, i, siz[i] ); } dinic(); if( n<=maxflow ) puts("YES"); else puts("NO"); } return 0; }