POJ 1149 PIGS (最大流)

连接:http://poj.org/problem?id=1149

第一道网络流,求最大流部分基本都是模板,主要的难点在于如何构图。

每个顾客、一个源点和一个汇点构成一个图,每个猪圈的第一个打开它的顾客 直接与源点相连 容量为该猪圈的猪的个数。不是首次打开猪圈的话,顾客j紧跟着顾客i之后打开某个猪圈,那么农场主可以根据j的需求来调整这个猪圈的流动路径。每个顾客到汇点相连容量为该顾客的需求,最终源点能提供所有的猪,汇点流出的就是所有顾客购买的猪的总数 也就是 农场主能卖出的猪。构造完图之后套一个最大流模板 ^ ^


/*--------------------- #headfile--------------------*/
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
/*----------------------#define----------------------*/
#define DRII(X,Y) int (X),(Y);scanf("%d%d",&(X),&(Y))
#define EXP 2.7182818284590452353602874713527
#define CASET int _;cin>>_;while(_--)
#define RII(X, Y) scanf("%d%d",&(X),&(Y))
#define DRI(X) int (X);scanf("%d", &X)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,n) for(int i=0;i<n;i++)
#define ALL(X) (X).begin(),(X).end()
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define RI(X) scanf("%d",&(X))
#define SZ(X) ((int)X.size())
#define PDI pair<double,int>
#define rson o<<1|1,m+1,r
#define PII pair<int,int>
#define MAX 0x3f3f3f3f
#define lson o<<1,l,m
#define MP make_pair
#define PB push_back
#define SE second
#define FI first
typedef long long ll;
template<class T>T MUL(T x,T y,T P){T F1=0;while(y){if(y&1){F1+=x;if(F1<0||F1>=P)F1-=P;}x<<=1;if(x<0||x>=P)x-=P;y>>=1;}return F1;}
template<class T>T POW(T x,T y,T P){T F1=1;x%=P;while(y){if(y&1)F1=MUL(F1,x,P);x=MUL(x,x,P);y>>=1;}return F1;}
template<class T>T gcd(T x,T y){if(y==0)return x;T z;while(z=x%y)x=y,y=z;return y;}
#define DRIII(X,Y,Z) int (X),(Y),(Z);scanf("%d%d%d",&(X),&(Y),&(Z))
#define RIII(X,Y,Z) scanf("%d%d%d",&(X),&(Y),&(Z))
const double pi = acos(-1.0);
const double eps = 1e-6;
const ll mod = 1000000007ll;
const int M = 1005;
const int N = 105;
using namespace std;

/*----------------------Main-------------------------*/
struct Edge {
    int to, c, rev;
    Edge() {}
    Edge(int _to, int _c, int _rev) {
        to = _to, c = _c, rev = _rev;
    }
};
vector<Edge> G[N];
int lv[N], iter[N];
int n, m;
void BFS(int s) {
    mem(lv, -1);
    queue<int> q;
    lv[s] = 0;
    q.push(s);
    while(!q.empty()) {
        int v = q.front(); q.pop();
        for(int i = 0; i < SZ(G[v]); i++) {
            Edge &e = G[v][i];
            if(e.c > 0 && lv[e.to] < 0) {
                lv[e.to] = lv[v] + 1;
                q.push(e.to);
            }
        }
    }
}
int dfs(int v, int t, int f) {
    if(v == t) return f;
    for(int &i = iter[v]; i < SZ(G[v]); i++) {
        Edge &e = G[v][i];
        if(e.c > 0 && lv[v] < lv[e.to]) {
            int d = dfs(e.to, t, min(f, e.c));
            if(d > 0) {
                e.c -= d;
                G[e.to][e.rev].c += d;
                return d;
            }
        }
    }
    return 0;
}
int MF(int s, int t) {
    int res = 0;
    for( ; ; ) {
        BFS(s);
        if(lv[t] < 0) return res;
        mem(iter, 0);
        int f;
        while((f = dfs(s, t, 1e9)) > 0) {
            res += f;
        }
    }
}
void add(int from, int to, int c) {
    G[from].PB( Edge(to, c, SZ(G[to])) );
    G[to].PB( Edge(from, 0, SZ(G[from]) - 1) );
}
int a[M], la[M];
void solve() {
    while(RII(m, n) != EOF) {
        for(int i = 1; i <= m; i++) RI(a[i]);
        for(int i = 0; i <= n + 1; i++) G[i].clear();
        int s = 0, t = n + 1;
        mem(la, 0);
        for(int i = 1; i <= n; i++) {
            DRI(A);
            for(int j = 0; j < A; j++) {
                DRI(x);
                int W = la[x] == 0 ? a[x] : 1e9;
                add(la[x], i, W);
                la[x] = i;
            }
            DRI(B);
            add(i, t, B);
        }
        printf("%d\n", MF(s, t));
    }
}

int main() {
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    CASET
    solve();
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值