• 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;
    }
  • 相关阅读:
    POJ 2017 No Brainer(超级水题)
    POJ 2017 No Brainer(超级水题)
    Poj1207 The 3n + 1 problem(水题(数据)+陷阱)
    Poj1207 The 3n + 1 problem(水题(数据)+陷阱)
    Poj1159 Palindrome(动态规划DP求最大公共子序列LCS)
    Poj1159 Palindrome(动态规划DP求最大公共子序列LCS)
    Poj1050_To the Max(二维数组最大字段和)
    Poj1050_To the Max(二维数组最大字段和)
    Poj 2602 Superlong sums(大数相加)
    Poj 2602 Superlong sums(大数相加)
  • 原文地址:https://www.cnblogs.com/WAautomaton/p/11031958.html
Copyright © 2020-2023  润新知