• 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 1
    3   0 2 1  1 1 1

    题目:P  —— 一台电脑由p个零件组成

       N —— 工厂有n台加工组装电脑的机器

      Q —— i-th机器每单位时间能工作的数量
     
    当每个未成品需要放入某个机器进一步加工的时候,它需要满足这台机器能正常工作的前提,
    即它必须满足某些零件已经组装好了。
    样例1: 前p个数字表示,进入i-th台机器,必须满足这些条件(0表示这个零件不能被安装 1表示这个零件必须被安装 2表示这个零件有无被安装无影响)
    后p个数字表示,某个未成品被i-th台机器加工完成后,满足了这些条件(0表示这个零件没被安装 1表示这个零件被安装了)
    问:怎么安排机器工作方案,能使得工作效率最大化,安排情况有很多,输出一种即可。

    思路:比较清楚,一个超级源点,一个超级汇点,一台机器需要拆成入点和出点,一台机器的入点和出点流量为该机器单位时间的工作量,其他点与点之间的流量就是INF了。
    重点就是哪些边能建立起来比较麻烦,图建好了,跑一个Dinic就OK了。
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <queue>
      5 #include <vector>
      6 using namespace std;
      7 
      8 const int N = 110,INF = (int)1e9;
      9 int p,n,tot;
     10 int G[N][N],head[N],lev[N];
     11 queue<int > que;
     12 struct info{
     13     int in[20],out[20];
     14     int cap;
     15 }info[N];//存机器的信息
     16 struct node{
     17     int to,nxt,flow;
     18 }e[N*N];
     19 
     20 void init_main(){
     21     for(int i = 1; i <= n; ++i)
     22         for(int j = 1; j <= n; ++j) G[i][j] = 0;
     23 
     24     for(int i = 0; i <= 2*n+1; ++i) head[i] = -1; tot = 0;
     25 }
     26 
     27 void init_bfs(){
     28     for(int i = 1; i <= 2*n+1; ++i) lev[i] = 0;
     29     while(!que.empty()) que.pop();
     30 }
     31 
     32 inline void add(int u,int v,int flow){
     33     e[tot].to = v;
     34     e[tot].flow = flow;
     35     e[tot].nxt = head[u];
     36     head[u] = tot++;
     37 }
     38 
     39 //是否可连边
     40 inline bool check(int x,int y){
     41     for(int i = 1; i <= p; ++i){
     42         if(info[y].in[i] == 2) continue;
     43         if(info[x].out[i] != info[y].in[i]) return false;
     44     }
     45     return true;
     46 }
     47 
     48 //建边
     49 void rebuild(){
     50     for(int i = 1; i <= n; ++i){
     51         if(check(0,i)){
     52             add(0,i,INF); add(i,0,0);
     53         }
     54         if(check(i,2*n+1)){
     55             add(i+n,2*n+1,INF); add(2*n+1,i+n,0);
     56         }
     57     }
     58     for(int i = 1; i <= n; ++i){
     59         for(int j = 1; j <= n; ++j){
     60             if(i == j){
     61                 add(i,i+n,info[i].cap); add(i+n,i,0);
     62             }
     63             else if(check(i,j)){
     64                 add(i+n,j,INF); add(j,i+n,0);
     65             }
     66         }
     67     }
     68 }
     69 
     70 int dfs(int now,int flow,int t){
     71     if(now == t) return flow;
     72     int to,sum = 0,tmp = 0;
     73     for(int o = head[now]; ~o; o = e[o].nxt){
     74         to = e[o].to;
     75         if((lev[to] == lev[now] +1) && e[o].flow && (tmp = dfs(to,min(flow - sum, e[o].flow),t))){
     76             //需要的路径流量  G数组来存机器之间的联系
     77             if(now > n && now < 2*n+1 && to != 2*n+1){
     78                 G[now-n][to] += tmp;
     79             }
     80             e[o].flow -= tmp;
     81             e[o^1].flow += tmp;
     82             if((sum += tmp) == flow) return sum;
     83         }
     84     }
     85     return sum;
     86 }
     87 
     88 bool bfs(int s,int t){
     89     init_bfs();
     90     que.push(0);
     91     while(!que.empty()){
     92         int now = que.front(); que.pop();
     93         for(int o = head[now]; ~o; o = e[o].nxt){
     94             int to = e[o].to;
     95             if(!lev[to] && e[o].flow){
     96                 lev[to] = lev[now] + 1;
     97                 que.push(to);
     98             }
     99         }
    100     }
    101     if(lev[t]) return true;
    102     else return false;
    103 }
    104 
    105 int mf(int s,int t){
    106     int max_flow = 0;
    107     while(bfs(s,t)){
    108         max_flow += dfs(s,INF,t);
    109         //cout << "max_flow  " << max_flow << endl;
    110     }
    111     return max_flow;
    112 }
    113 
    114 int main(){
    115 
    116     while(~scanf("%d%d",&p,&n)){
    117         init_main();
    118         //读入信息  0超级源点   2*n+1超级汇点
    119         for(int i = 1; i <= n; ++i){
    120             scanf("%d",&info[i].cap);
    121             for(int j = 1; j <= p; ++j) scanf("%d",&info[i].in[j]);
    122             for(int j = 1; j <= p; ++j) scanf("%d",&info[i].out[j]);
    123         }
    124         info[0].cap = INF; info[2*n+1].cap = INF;
    125         for(int i = 1; i <= p; ++i){
    126             info[0].out[i] = 0;
    127             info[2*n+1].in[i] = 1;
    128         }
    129         //建图
    130         rebuild();
    131         //Dinic
    132         int _mf = mf(0,2*n+1),line = 0;
    133         //统计需要的联系数量
    134         for(int i = 1; i <= n; ++i){
    135             for(int j = 1; j <= n; ++j){
    136                 if(G[i][j]) ++line;
    137             }
    138         }
    139         printf("%d %d
    ",_mf,line);
    140         //输出联系
    141         for(int i = 1; i <= n; ++i){
    142             for(int j = 1; j <= n; ++j){
    143                 if(G[i][j]) printf("%d %d %d
    ",i,j,G[i][j]);
    144             }
    145         }
    146      }
    147 
    148     return 0;
    149 }
     
  • 相关阅读:
    Scala-文件操作
    python-数字
    python-访问模型
    scala-包
    Scala对象
    Scala-类
    sql存储过程
    sql视图
    sql基本语句
    sql中级语句
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/12238750.html
Copyright © 2020-2023  润新知