`
java-mans
  • 浏览: 11455585 次
文章分类
社区版块
存档分类
最新评论

POJ 3436 最大流

 
阅读更多

很羞愧啊 , 题都没看咋懂


翻译见:http://hi.baidu.com/lewutian/blog/item/1b0709220085b7fed7cae28b.html/cmtid/87a1a0ad1aebe6064b36d60e

题解参考了:http://zhyu.me/acm/poj-3436.html,BUPT一位现役神牛的blog

每台机器分输入输出,很显然直接拆点,每个点的(in)和(out)间连一条容量为该机器产量的边,然后对于输入没有限制的点,从源点向该点的(in)连一条容量为inf的边,对于输出是P个零件都有的点,从该点的(out)向汇点连一条容量inf的边,然后枚举所有点,如果某点的输出满足另一点的输入,则连一条inf的边。建图后直接求最大流即可,要输出解集,只需要最后遍历所有点的(out) ,看其所连的所有边中不包括终点的边,且流量大于0的边即为所求。


/*
ID: CUGB-wwj
PROG:
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define INF 1111111111
#define MAXN 222
#define MAXM 444444
#define PI acos(-1.0)
using namespace std;
struct node
{
    int ver;    // vertex
    int cap;    // capacity
    int flow;   // current flow in this arc
    int next, rev;
}edge[MAXM];
int dist[MAXN], numbs[MAXN], src, des, n;
int head[MAXN], e, p;
int ans[MAXM][3];
struct abcd
{
    int val;
    int in[15],out[15];
}x[MAXN];
int srcout[15], desin[15];
void add(int x, int y, int c)
{       //e记录边的总数
    edge[e].ver = y;
    edge[e].cap = c;
    edge[e].flow = 0;
    edge[e].rev = e + 1;        //反向边在edge中的下标位置
    edge[e].next = head[x];   //记录以x为起点的上一条边在edge中的下标位置
    head[x] = e++;           //以x为起点的边的位置
    //反向边
    edge[e].ver = x;
    edge[e].cap = 0;  //反向边的初始网络流为0
    edge[e].flow = 0;
    edge[e].rev = e - 1;
    edge[e].next = head[y];
    head[y] = e++;
}
void rev_BFS()
{
    int Q[MAXN], qhead = 0, qtail = 0;
    for(int i = 1; i <= n; ++i)
    {
        dist[i] = MAXN;
        numbs[i] = 0;
    }
    Q[qtail++] = des;
    dist[des] = 0;
    numbs[0] = 1;
    while(qhead != qtail)
    {
        int v = Q[qhead++];
        for(int i = head[v]; i != -1; i = edge[i].next)
        {
            if(edge[edge[i].rev].cap == 0 || dist[edge[i].ver] < MAXN)continue;
            dist[edge[i].ver] = dist[v] + 1;
            ++numbs[dist[edge[i].ver]];
            Q[qtail++] = edge[i].ver;
        }
    }
}
void init()
{
    e = 0;
    memset(head, -1, sizeof(head));
}
int maxflow()
{
    int u, totalflow = 0;
    int Curhead[MAXN], revpath[MAXN];
    for(int i = 1; i <= n; ++i)Curhead[i] = head[i];
    u = src;
    while(dist[src] < n)
    {
        if(u == des)     // find an augmenting path
        {
            int augflow = INF;
            for(int i = src; i != des; i = edge[Curhead[i]].ver)
                augflow = min(augflow, edge[Curhead[i]].cap);
            for(int i = src; i != des; i = edge[Curhead[i]].ver)
            {
                edge[Curhead[i]].cap -= augflow;
                edge[edge[Curhead[i]].rev].cap += augflow;
                edge[Curhead[i]].flow += augflow;
                edge[edge[Curhead[i]].rev].flow -= augflow;
            }
            totalflow += augflow;
            u = src;
        }
        int i;
        for(i = Curhead[u]; i != -1; i = edge[i].next)
            if(edge[i].cap > 0 && dist[u] == dist[edge[i].ver] + 1)break;
        if(i != -1)     // find an admissible arc, then Advance
        {
            Curhead[u] = i;
            revpath[edge[i].ver] = edge[i].rev;
            u = edge[i].ver;
        }
        else        // no admissible arc, then relabel this vertex
        {
            if(0 == (--numbs[dist[u]]))break;    // GAP cut, Important!
            Curhead[u] = head[u];
            int mindist = n;
            for(int j = head[u]; j != -1; j = edge[j].next)
                if(edge[j].cap > 0)mindist = min(mindist, dist[edge[j].ver]);
            dist[u] = mindist + 1;
            ++numbs[dist[u]];
            if(u != src)
                u = edge[revpath[u]].ver;    // Backtrack
        }
    }
    return totalflow;
}

bool check(int* a, int* b)
{
    for(int i = 0; i < p; i++) if(a[i] + b[i] == 1)    return 0;
    return 1;
}
int main()
{
    init();
    int nt;
    scanf("%d%d", &p, &nt);
    n = 2 * nt + 2;
    src = 1;
    des = n;
    for(int i = 0; i < p; i++)
    {
        srcout[i] = 0;
        desin[i] = 1;
    }
    for(int i = 1; i <= nt; i++)
    {
        scanf("%d", &x[i].val);
        for(int j = 0; j < p; j++) scanf("%d", &x[i].in[j]);
        for(int j = 0; j < p; j++) scanf("%d", &x[i].out[j]);
    }
    for(int i = 1; i <= nt; i++)
    {
        if(check(srcout, x[i].in)) add(src, i + 1, INF);
        if(check(x[i].out, desin)) add(i + 1 + nt, des, INF);
        add(i + 1, i + nt + 1, x[i].val);
        for(int j = 1; j <= nt; j++) if(i != j && check(x[i].out, x[j].in)) add(i + 1 + nt, j + 1, INF);
    }
    rev_BFS();
    printf("%d ", maxflow());
    int cnt = 0;
    for(int i = nt + 2; i <= des - 1; i ++)
        for(int j = head[i]; j != -1; j = edge[j].next)
        {
            if(edge[j].ver != des && edge[j].flow > 0)
            {
                ans[cnt][0] = i - nt - 1;
                ans[cnt][1] = edge[j].ver - 1;
                ans[cnt++][2] = edge[j].flow;
            }
        }
    printf("%d\n", cnt);
    for(int i = 0; i < cnt; i++)
    printf("%d %d %d\n", ans[i][0], ans[i][1], ans[i][2]);
    return 0;
}


分享到:
评论

相关推荐

    POJ2516__最小费用最大流

    poj2516代码最小费用最大流

    POJ3308-Paratroopers 【Dinic算法求最大流】

    【二分图顶点覆盖-&gt;最小割-&gt;最大流-&gt;Dinic算法求解】 解题报告+AC代码 http://hi.csdn.net/!s/WKVPR0 ----&gt; 我的所有POJ解题报告 http://blog.csdn.net/lyy289065406/article/details/6642573

    POJ2195-Going Home【费用流】

    北大POJ2195-Going Home【费用流】 解题报告+AC代码 http://blog.csdn.net/lyy289065406/article/details/6732762

    北大oj 题目分类

    初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法.... (4)递推.... (5)构造法.(poj3295) ... (6)最大流的增广路算法(KM算法). (poj1459,poj3436) ......

    网络流(最大流)SAP源码

    最短增广路算法的实现 并加上了gap优化和当前弧优化 代码为POJ3469(dual core)的源码

    acm_code_20053565

    acm code of 20053565 poj onlinejudge 高精度 DP 图论 算法 最大流 最小生成树 线段树

    大学课程中相关一些算法题

    4.1 最大乘积问题 4.2 魔术数字游戏 4.3 Jimmy's Bad Day 5.1 循环赛的日程表问题 5.2 猴子选大王 5.3 售货员的难题 6.1 最大字段和问题 6.2 N*N方阵 6.3 埃及分数最好表达式

    浙江大学ACM模板 计算几何,图论,数据结构,经典题的模板

    8.10 最大网络流 175 8.11 最小费用流 180 8.12 最大团问题 182 8.13 二分图匹配 184 8.14 带权的最优二分图匹配 184 9.搜索算法概略 187 9.1 迭代深搜+IDA* 187 9.2 分之界限法(深搜) 189 9.3 A* 8数码问题( ...

    挑战程序设计竞赛(第2版)

    3.5.1 最大流 3.5.2 最小割 3.5.3 二分图匹配 3.5.4 一般图匹配 3.5.5 匹配、边覆盖、独立集和顶点覆盖 3.5.6 最小费用流 3.5.7 应用问题 3.6 与平面和空间打交道的计算几何 3.6.1 计算几何基础 3.6.2 极限情况 ...

    leetcode2sumc-coding:用C++编码

    个最大元素:# 递归 排列:#、# 哈希 二和:# 同构字符串:# 注意:构建堆,O(n); 提取根并重建 O(logn) 从数据流中查找中位数:# 合并 k 个排序的数组/列表:# 链表 #,# 树 遍历:前序、中序、后序、水平 同一棵...

    kuangbin acm模板超级好用

    2.6 随机素数测试和大数分解 (POJ 1811) . . . . . . . . . . . . . . . . . . . . . . . 29 2.7 欧拉函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.7.1 分解质因素求...

Global site tag (gtag.js) - Google Analytics