图论专题-网络流

这里写图片描述

思路:
构图:i 和 j 公用元素k[i][j],把数组A[i] , B[j]分别看成节点,那么A[i]可以流向B[j]大小最多为k[i][j],最少1的流量,但是网络流中最小流量为0,所以每行的和减去m,每列的和减去n,(每个元素减1).源点连A[i],容量为A[i],B[j]连汇点,容量为B[j],A[i] , B[j]连容量19的边。跑网络流,如果到汇点的和 == 矩阵的和,那么存在结果。将A[i] 到B[j]的流量加1输出即可

Code:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 1e3+6;
int A[AX];
int b[AX];
int m , n ;
struct Node{
    int from , to , cap , flow;
    Node( int u , int v , int c , int f ):from(u),to(v),cap(c),flow(f){}
};

std::vector<Node> edge;
std::vector<int> G[AX];
std::vector<int> vec;
int a[AX];
int p[AX];
int res[AX][AX];
void init(){
    for( int i = 0 ; i < n ; i++ ) G[i].clear();
    for( int i = 0 ; i < m ; i++ ) G[i+n].clear();
    edge.clear();
}

int st = 100;
int ed = 101;
void addedge( int u ,int v ,int cap ){
    edge.push_back( Node( u , v , cap , 0 ) );
    edge.push_back( Node( v , u , 0 , 0 ) );

    int size = edge.size();
    if( u != st && v != ed ){
        vec.push_back( size - 2 );
    }
    G[u].push_back(size-2);
    G[v].push_back(size-1);
}

int Maxflow( int s , int t ){
    int flow = 0;
    while( true ){
        memset( a, 0 , sizeof(a) );
        queue<int>que;
        que.push(s);
        a[s] = INF;
        while( !que.empty() ){
            int x = que.front();
            que.pop();
            for( int i = 0 ; i < G[x].size() ; i++ ){
                Node& e = edge[G[x][i]];
                if( !a[e.to] && e.cap > e.flow ){
                    p[e.to] = G[x][i];
                    a[e.to] = min( a[x] , e.cap - e.flow );
                    que.push(e.to);
                }
            }
            if( a[t] ) break;
        }
        if( !a[t] ) break;
        for( int i = t ; i != s ; i = edge[p[i]].from ){
            edge[p[i]].flow += a[t];
            res[ edge[p[i]].from ][ i ] = edge[p[i]].flow;
            edge[p[i]^1].flow -= a[t];
        }
        flow += a[t];
    }
    return flow;
}

int main(){
    int sum = 0 ;
    scanf("%d%d",&n,&m);
    init();
    for( int i = 0 ; i < n ; i++ ){
        scanf("%d",&A[i]);
        A[i] -= m;
        addedge( st , i , A[i] );
    } 
    for( int i = 0 ; i < m ; i++ ){
        scanf("%d",&b[i]);
        b[i] -= n ;
        addedge( i + n , ed , b[i] );
        sum += b[i];
    }   

    for( int i = 0 ; i < n ; i ++ ){
        for( int j = 0 ; j < m ; j ++ ){
            addedge( i , j + n , 19 );
        }
    }

    int ans = Maxflow( st , ed );   

    if( ans == sum ){
        printf("Yes\n");
        for( int i = 0 ; i < vec.size() ; i++ ){
            if( i && i % m == 0 ){
                printf("\n");
            }
            printf("%d ",edge[vec[i]].flow+1);
        }
    }else{
        printf("No\n");
    }
    return 0 ;
}

猜你喜欢

转载自blog.csdn.net/frankax/article/details/80494365