POJ-1149 PIGS

来源:互联网 发布:网络加速器推荐 编辑:程序博客网 时间:2024/06/06 13:58

题目大意:

有M个猪圈,每个猪圈都有把锁,卖猪的本身是没有钥匙的,现在有N个顾客要来买猪,而且第i个顾客有a[i]把锁的钥匙,能打开k1,k2,k3...kai的猪圈,称这个时候,你可以调整k1,k2,k3...kai号猪圈里面猪的个数。现在已知每个客户要买多少猪,有哪些锁。问你一天最多能卖出去多少猪。

解题思路:

把顾客当作除了源点和汇点的节点,并且设置一个源点和汇点。

把第一次访问ai个猪圈的顾客与源点添加一条边,容量为开始时猪圈中猪的数目。把在他之后第二个访问该猪圈的顾客与他再添加一条边,容量为INF。以此类推。

再把每个顾客与汇点添加一条边容量为要买猪的个数。

这样构图就完成了。然后直接求网络流即可

代码:

#include <queue>#include <cstdio>#include <cstring>using namespace std;typedef struct node{    int v, cap, nxt;    node(int _v = 0, int _cap = 0, int _nxt = 0): v(_v), cap(_cap), nxt(_nxt){}}Edge;const int maxn = 200;const int maxm = 2e4 + 10;const int INF = 0x3f3f3f3f;int tot;Edge edge[maxm];int dis[maxn];int head[maxm], num[1005], vis[maxn];inline int Min(int a, int b){    return a < b ? a : b;}void add(int u, int v, int cap){    edge[tot] = Edge(v, cap, head[u]);    head[u] = tot++;    edge[tot] = Edge(u, 0, head[v]);    head[v] = tot++;}int bfs(int s, int t){    queue<int> q;    while(!q.empty()) q.pop();    memset(dis, 0, sizeof(dis));    q.push(s); dis[s] = 1;    while(!q.empty()){        int u = q.front(); q.pop();        if(u == t) break;        for(int i = head[u]; ~i; i = edge[i].nxt){            Edge &e = edge[i];            if(!dis[e.v] && e.cap){                dis[e.v] = dis[u] + 1;                q.push(e.v);            }        }    }    return dis[t];}int dfs(int u, int v, int f){    if(u == v) return f;    int sum = 0;    for(int i = head[u]; ~i; i = edge[i].nxt){        Edge &e = edge[i];        if(e.cap && dis[e.v] == dis[u] + 1){            int ret = dfs(e.v, v, Min(f, e.cap));            sum += ret; f -= ret;            e.cap -= ret; edge[i^1].cap += ret;        }    }    return sum;}int dinic(int s, int t){    int ret = 0;    while(bfs(s, t))        ret += dfs(s, t, INF);    return ret;}int main(){    int a, k, m, n, sum, val;    while(~scanf("%d%d", &m, &n)){        tot = 0;        memset(vis, 0, sizeof(vis));        memset(head, -1, sizeof(head));        for(int i = 1; i <= m; ++i){            scanf("%d", &num[i]);        }        for(int i = 1; i <= n; ++i){            scanf("%d", &a);            sum = 0;            for(int j = 1; j <= a; ++j){                scanf("%d", &k);                if(!vis[k]){ vis[k] = i; sum += num[k]; }                else {                    if(vis[k] == i) continue;                    add(vis[k], i, INF);                    vis[k] = i;                }            }            scanf("%d", &val);            if(sum > 0) add(0, i, sum);            add(i, n + 1, val);        }        printf("%d\n", dinic(0, n + 1));    }    return 0;}


0 0
原创粉丝点击