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;
    }
  • 相关阅读:
    CentOS6.7 mysql5.6.33修改数据文件位置
    win8 win10 安装msi 提示2502、2503的错误代码
    2016年国内开源镜像站点汇总
    eclipse创建本地maven
    maven添加sqlserver的jdbc驱动包
    CentOS6.5下RPM方式安装mysql5.6.33
    linux中~和/的区别
    Linux命令学习(22):ss命令
    Linux命令学习(21):netstat命令
    Linux命令学习(20):traceroute命令
  • 原文地址:https://www.cnblogs.com/vongang/p/2251278.html
Copyright © 2011-2022 走看看