zoukankan      html  css  js  c++  java
  • POJ_1149 PIGS (网络流)

      /*拿到这题确实不知道怎么建图,问师兄,师兄讲了半天我也没听懂,后来看了 
    Edelweiss大牛的《网络流建模汇总》,第一个就是讲的这道题。

    大体思路是建立一个很直观的模型,但是复杂度太高,然后根据所找到的规律删边,最后
    可以得到简单的建图规律:

    1、从源点S到访问第i个猪圈的第一个人建一条边,容量Ci 就是猪圈里猪的头数,后边如果
    再有顾客访问第i个猪圈,则从一个访问者到后来访问的顾客建一条边,容量为 +∞ 表示他
    们之间可以相互联通。

    2、如果从源点到一名顾客有多条边,则把这些边的合成一条边,容量累加。

    3、每一个顾客到汇点T建一条边,容量就是顾客要买的猪数。


    PS:网络流难的不是Dinic,SAP什么的,难的是建图啊。。。T_T

    My Code:
    */

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>

    using namespace std;

    const int N = 110;
    const int M = 1024;
    const int inf = 0x6fffffff;

    struct pig {
    int cos[N];
    int num;
    int n;
    }p[M];

    int T;
    int c[N];
    int g[N][N];
    int layer[N];
    bool vis[N];

    bool Layer() {
    deque<int> q;
    int i, v;
    memset(layer, -1, sizeof(layer));
    q.push_back(0);
    layer[0] = 1;

    while( !q.empty() ) {
    v = q.front();
    q.pop_front();

    for( i = 0; i <= T; i++ ) {
    if(g[v][i] > 0 && layer[i] == -1) {
    layer[i] = layer[v] + 1;
    if(i == T) {q.clear(); return true;}
    else q.push_back(i);
    }
    }
    }
    return false;
    }

    int Dinic() {
    deque<int> q;
    int i, v, ve, vs, min, min_s, sum = 0;

    while(Layer()) {
    memset(vis, false, sizeof(vis));
    q.push_back(0);
    vis[0] = true;

    while(!q.empty()) {
    v = q.back();
    if(v == T) {
    min = inf;
    for(i = 1; i < q.size(); i++) {
    vs = q[i-1], ve = q[i];
    if(g[vs][ve] > 0 && min > g[vs][ve]) {
    min = g[vs][ve];
    min_s = vs;
    }
    }
    sum += min;
    for(i = 1; i < q.size(); i++) {
    vs = q[i-1]; ve = q[i];
    if(g[vs][ve] > 0) {
    g[vs][ve] -= min;
    g[ve][vs] += min;
    }
    }
    while(!q.empty() && q.back() != min_s) {
    vis[q.back()] = false;
    q.pop_back();
    }
    } else {
    for(i = 0; i <= T; i++) {
    if(g[v][i] > 0 && !vis[i] && layer[i] == layer[v] + 1) {
    vis[i] = true;
    q.push_back(i);
    break;
    }
    }
    if(i > T) q.pop_back();
    }
    }
    }
    return sum;
    }

    int main() {
    //freopen("data.in", "r", stdin);

    int N, M, i, k, j, x;
    scanf("%d%d", &M, &N);

    for(i = 1; i <= M; i++) {
    scanf("%d", &p[i].num);
    }
    for(i = 1; i <= N; i++) {
    scanf("%d", &k);
    for(j = 1; j <= k; j++) {
    scanf("%d", &x);
    p[x].cos[p[x].n++] = i;
    }
    scanf("%d", &c[i]);
    }
    T = N + 1;
    for(i = 1; i <= M; i++) {
    if(p[i].n != 0) {
    g[0][p[i].cos[0]] += p[i].num;
    for(j = 1; j < p[i].n; j++) {
    g[p[i].cos[0]][p[i].cos[j]] = inf;
    }
    }
    }
    for(i = 1; i <= N; i++)
    g[i][T] = c[i];

    printf("%d\n", Dinic());
    return 0;
    }
  • 相关阅读:
    BZOJ 1101 莫比乌斯函数+分块
    BZOJ 2045 容斥原理
    BZOJ 4636 (动态开节点)线段树
    BZOJ 2005 容斥原理
    BZOJ 2190 欧拉函数
    BZOJ 2818 欧拉函数
    BZOJ 3123 主席树 启发式合并
    812. Largest Triangle Area
    805. Split Array With Same Average
    794. Valid Tic-Tac-Toe State
  • 原文地址:https://www.cnblogs.com/vongang/p/2251278.html
Copyright © 2011-2022 走看看