题目

http://poj.org/problem?id=3436

题意

有一条生产线,生产的产品共有p个(p<=10)零件,生产线上共有n台(n<=50)机器,每台机器可以每小时加工Qi个产品,但有输入要求,即对于部件Pi,输入要求会说明要求其存在(1),不存在(0)或者无要求(2),每台机器的输出状态是一定的,会说明经过该机器加工后某个零件是否存在(1),不存在(0)。所有零件都存在(状态都为1时)组装成功,问如何重新安排生产线这张图使得每小时输出的产品数量最多?或者可以简单理解为:在有向图中有n个结点,它们有允许的状态输入,有确定的状态输出,每个点有自身容量限制,状态输入全为0的结点都为最大流起点,状态输出全为1的结点都为最大流终点,求最大流容量。

思路

题目索引中这道题可以使用KM算法,但是我采用了较为简单的思路。

首先对于某两个机器结点i,j,从i出发能否连接j可以直接穷举j的输入状态是否符合i的输出状态。

这样就能得到初始的图,而在这张图中,由于作为起点或终点的结点可能有很多个,所以需要建立超级起点,从超级起点出发连接所有起点,建立超级终点,从所有终点出发连接超级终点。

但是此时这张图上只有点有流量限制,边没有流量限制,所以需要把机器结点拆分为两个结点,两个结点一个为入点,一个为出点,入点到出点之间连一条有向边,容量限制为点的流量限制,这样就能够简单运用最大流算法处理这个问题。注意此时原先从这个机器节点出发的所有边都改从出点出发,所有到这个机器节点的弧都改为从入点到达。

感想

这道题题目清晰,注意可能是多组数据。是最大流入门的好题。

很久没有做题了,打算重拾这个习惯,代码中的最大流是根据记忆重现的,可能效率不太高。

代码

#include <cstdio>
#include <map>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <iostream>
#include <assert.h>
#include <sstream>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <iterator>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld; const int maxp = 10;
const int maxn = 104;
const int maxm = 11000;
const int inf = 0x3ffffff; int p,n; int input[maxn][maxp];
int output[maxn][maxp];
int v[maxn]; int oldg[maxn][maxn];
int ogn[maxn]; int first[maxn];
struct edge
{
int nxt, to, fromId, toId, c;
} g[maxm];
int gn; bool vis[maxn]; bool matchIn(int prev, int nxt)
{
for(int i = 0; i < p; i++)
{
int sNxt = nxt>n?1:input[nxt][i];
int sPrev = nxt?output[prev][i]:0;
if(sNxt != 2 && sNxt != sPrev)return false;
}
return true;
} void genOldGraph()
{
for(int i = 0; i <= n; i++)
{
for(int j = 1; j <= n+1; j++)
{
if(i != j && matchIn(i, j))
{
oldg[i][ogn[i]++] = j;
}
}
}
} bool testConnect(int s)
{
if(s == n + 1)return true;
vis[s] = true;
for(int i = 0; i < ogn[s]; i++)
{
if(!vis[oldg[s][i]])
if(testConnect(oldg[s][i]))return true;
}
return false;
} inline int inId(int f)
{
return (f?(f<=n?2*f:(2*f-1)):0);
} inline int outId(int t)
{
return (t?(2 * t - 1):0);
} void addEdge(int fId, int tId)
{
// n+1->2n+1, 0->0, 1...n->(1,2),(3,4),(5,6)...(2n-1,2n)
int f = fId==tId?outId(fId):inId(fId);
int t = fId==tId?inId(fId):outId(tId);
int c = fId==tId?v[fId]:inf;
g[gn].nxt = first[f];
g[gn].fromId = fId;
g[gn].toId = tId;
g[gn].c = c;
g[gn].to = t;
first[f] = gn;
gn++;
g[gn].nxt = first[t];
g[gn].fromId = tId;
g[gn].toId = fId;
g[gn].c = 0;
g[gn].to = f;
first[t] = gn;
gn++;
// printf("%d to %d(%d to %d): %d\n",fId, tId, f, t, c);
} bool genNewGraph()
{
if(!testConnect(0))return false;
for(int i = 0; i <= n + 1; i++)
{
for(int j = 0; j < ogn[i]; j++)
{
addEdge(i, oldg[i][j]);
}
}
for(int i = 1; i <= n; i++)
{
addEdge(i,i);
}
memset(vis,false,sizeof vis);
return true;
} int maxflowsub(int s, int f, int flow){
if(s == 2 * n + 1)return flow;
int ans = 0;
vis[s] = true;
for(int p = first[s];p != -1;p=g[p].nxt){
if(g[p].to == f || g[p].c == 0)continue;
int t = g[p].to;
if(!vis[t] && (ans = maxflowsub(t, s, min(flow, g[p].c)))){
g[p].c -= ans;
g[p^1].c += ans;
return ans;
}
}
return 0;
} int maxflow()
{
int ans = 0;
int sub = 0;
while((sub = maxflowsub(0, -1, inf))){
ans += sub;
memset(vis,false,sizeof vis);
}
return ans;
} void genResult(int ans){
int m = 0;
for(int i = 0;i < gn;i+=2){
if(g[i].fromId && g[i].toId <= n && g[i].fromId != g[i].toId && g[i].c < inf){
m++;
}
}
printf("%d %d\n", ans, m);
for(int i = 0;i < gn;i+=2){
if(g[i].fromId && g[i].toId <= n && g[i].fromId != g[i].toId && g[i].c < inf){
printf("%d %d %d\n", g[i].fromId, g[i].toId, g[i + 1].c);
}
}
} void init()
{
for(int i = 1; i <= n; i++)
{
scanf("%d", v + i);
for(int j = 0; j < p; j++)
{
scanf("%d", input[i] + j);
}
for(int j = 0; j < p; j++)
{
scanf("%d", output[i] + j);
}
}
memset(ogn, 0, sizeof ogn);
memset(vis, false, sizeof vis);
memset(first, -1, sizeof first);
gn = 0;
} void solve(){
genOldGraph();
if(!genNewGraph()){
puts("0 0");
}else{
int ans = maxflow();
genResult(ans);
}
} int main()
{
while(scanf("%d%d",&p, &n) == 2)
{
init();
solve();
}
return 0;
}

POJ 3436 ACM Computer Factory 最大流,拆点 难度:1的更多相关文章

  1. Poj 3436 ACM Computer Factory (最大流)

    题目链接: Poj 3436 ACM Computer Factory 题目描述: n个工厂,每个工厂能把电脑s态转化为d态,每个电脑有p个部件,问整个工厂系统在每个小时内最多能加工多少台电脑? 解题 ...

  2. poj 3436 ACM Computer Factory 最大流+记录路径

    题目 题意: 每一个机器有一个物品最大工作数量,还有一个对什么物品进行加工,加工后的物品是什么样.给你无限多个初始都是000....的机器,你需要找出来经过这些机器操作后最多有多少成功的机器(111. ...

  3. POJ 3436 ACM Computer Factory (网络流,最大流)

    POJ 3436 ACM Computer Factory (网络流,最大流) Description As you know, all the computers used for ACM cont ...

  4. POJ - 3436 ACM Computer Factory 网络流

    POJ-3436:http://poj.org/problem?id=3436 题意 组配计算机,每个机器的能力为x,只能处理一定条件的计算机,能输出特定的计算机配置.进去的要求有1,进来的计算机这个 ...

  5. POJ - 3436 ACM Computer Factory(最大流)

    https://vjudge.net/problem/POJ-3436 题目描述:  正如你所知道的,ACM 竞赛中所有竞赛队伍使用的计算机必须是相同的,以保证参赛者在公平的环境下竞争.这就是所有这些 ...

  6. POJ 3436 ACM Computer Factory(最大流+路径输出)

    http://poj.org/problem?id=3436 题意: 每台计算机包含P个部件,当所有这些部件都准备齐全后,计算机就组装完成了.计算机的生产过程通过N台不同的机器来完成,每台机器用它的性 ...

  7. POJ 3436 ACM Computer Factory (拆点+输出解)

    [题意]每台计算机由P个零件组成,工厂里有n台机器,每台机器针对P个零件有不同的输入输出规格,现在给出每台机器每小时的产量,问如何建立流水线(连接各机器)使得每小时生产的计算机最多. 网络流的建图真的 ...

  8. POJ 3436 ACM Computer Factory

    题意:   为了追求ACM比赛的公平性,所有用作ACM比赛的电脑性能是一样的,而ACM董事会专门有一条生产线来生产这样的电脑,随着比赛规模的越来越大,生产线的生产能力不能满足需要,所以说ACM董事会想 ...

  9. kuangbin专题专题十一 网络流 POJ 3436 ACM Computer Factory

    题目链接:https://vjudge.net/problem/POJ-3436 Sample input 1 3 4 15 0 0 0 0 1 0 10 0 0 0 0 1 1 30 0 1 2 1 ...

随机推荐

  1. d3选择全部子节点,不知道class和id

    https://github.com/d3/d3-selection/issues/63 selection.selectAll("*")

  2. (转)Linux下设置和查看环境变量

    原文地址:<Linux下设置和查看环境变量> Linux的变量种类 按变量的生存周期来划分,Linux变量可分为两类: 1. 永久的:需要修改配置文件,变量永久生效. 2. 临时的:使用e ...

  3. python Scrapy 常见问题记录

    ImportError: No module named win32api 处理办法 windows系统上出现这个问题的解决需要安装Py32Win模块,但是直接通过官网链接装exe会出现几百个错误,更 ...

  4. 解决ios下的微信页面背景音乐无法自动播放问题

    在做各种html5场景页面的时候,插入背景音乐是一个很普遍的需求,我们都知道,ios下的safari是无法自动播放音乐的,以至于现在行程一种认知,ios是没有办法自动播放媒体资源的,这个认知其实是错误 ...

  5. 验证码之SimpleCaptcha (一)

    在captcha中,两个比较著名的框架验证码有Jcaptcha和simpleCaptcha,Jcaptcha太庞大了,所以我选择了简单的SimpleCaptcha       simpleCaptch ...

  6. 质控工具之cutadapt的使用方法

    cutadapt 参考:用cutadapt软件来对双端测序数据去除接头 fastqc可以用于检测,检测出来了怎么办? 看了几篇高水平文章,有不少再用cutadapt,虽然有时候数据真的不错,但是还是要 ...

  7. English trip EM2-LP-3A Gifts Teacher:Patrick

    课上内容(Lesson) 词汇(Key Word ) Identify   vt. 确定:识别:使参与:把…看成一样 objects  n. 物体(object的复数):目标  # UFO   =   ...

  8. 安卓中使用OkHttp发送数据请求的两种方式(同、异步的GET、POST) 示例-- Android基础

    1.首先看一下最终效果的截图,看看是不是你想要的,这个年代大家都很忙,开门见山很重要! 简要说下,点击不同按钮可以实现通过不同的方式发送OkHttp请求,并返回数据,这里请求的是网页,所以返回的都是些 ...

  9. 基于windows使用fabric将gitlab的文件远程同步到服务器(本地)

    # -*- coding: utf-8 -*- from fabric.api import env, run, local, put from fabric.operations import su ...

  10. linux bash基本特性

    一.bash 基础特性 (1)命令历史的功能 history: 环境变量 HISTSIZE:命令历史记录的条数 HISTFILE: ~/.bash_history 每个用户都有自己独立的命令历史文件 ...