码迷,mamicode.com
首页 > 其他好文 > 详细

POJ3436:ACM Computer Factory-最大流

时间:2018-08-04 21:39:40      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:两台   必须   return   mat   fill   lock   ack   alt   define   

目录

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

目录

题意:传送门

?原题目描述在最下面。
?题目真难读懂

  • \(n\)台机器,每台机器有\(p\)个部分,每台机器有\(p\)个输入输出规格。每台机器有一个产量参数,\(p\)\(0or1or2\)代表输入规格,\(p\)\(0or1\)代表输出规格。
  • 机器输入规格:0:该部分不能存在,1:该部分必须存在,2:该部分存不存在都行
  • 机器输出规格:0:该部分不存在,1:该部分存在

  • 输出:最大产量,必须存在的机器链
  • 对每条机器链输出链接的两个机器,及其产量。


思路:

?超级源点向输入规格不存在1的机器连边,流容量为其标准产量。
?输出规格全为1的机器向超级汇点连边,流容量为其标准产量。
?对于输出和输入能相互匹配形成产业链的机器连一条边,流容量为两台机器标准产量的较小值。

?细节见代码。

AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#define mme(a,b) memset((a),(b),sizeof((a)))  
#define test printf("***\n")
#define fuck(x) cout<<"* "<<x<<"\n"
#define iis std::ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int MXN = 1e4+7;
const int MXE = 1e7+7;
struct DINIC{
  int tot,vt,vs;
  int d[MXN],head[MXN];
  struct lp{int u,c;
    int v,w,nex;
  }cw[MXE];
  void add_edge(int a,int b,int c){
    cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c;
    head[a]=tot;cw[tot].u=a;cw[tot].c=c;
    cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0;
    head[b]=tot;
  }
  bool bfs(){
    memset(d,-1,sizeof(d));
    queue<int>Q;
    Q.push(vt);d[vt]=0;
    while(!Q.empty()){
      int u=Q.front();
      Q.pop();
      for(int i=head[u];i!=-1;i=cw[i].nex){
        int v=cw[i].v;
        if(cw[i^1].w&&d[v]==-1){
          d[v]=d[u]+1;
          Q.push(v);
        }
      }
    }
    return d[vs]!=-1;
  }
  int dfs(int x,int f){
    if(x==vt||f==0) return f;
    int use=0,w;
    for(int i=head[x];i!=-1;i=cw[i].nex){
      int to=cw[i].v;
      if(d[to]==d[x]-1 && cw[i].w){
        w=dfs(to,min(cw[i].w,f-use));
        cw[i].w-=w,cw[i^1].w+=w;
        use+=w;
        if(use==f) return f;
      }
    }
    return use;
  }
  void init(int st,int ed){
    tot=-1;
    memset(head,-1,sizeof(head));
    vs=st;vt=ed;
  }
  int max_flow(){
    int ans=0;
    while(bfs())ans+=dfs(vs,INF);
    return ans;
  }
  void solve(int n){
    int ans=max_flow(),cnt=0;
    if(ans==0){
      printf("0 0\n");
      return;
    }
    vector<int> a,b,c;
    for(int i=0;i<=tot;i+=2){
      if(cw[i].w!=cw[i].c&&cw[i].u!=vs&&cw[i].v!=vt&&cw[i].u+n!=cw[i].v&&cw[i].u!=cw[i].v){
        if(cw[i].u>n)cw[i].u-=n;if(cw[i].v>n)cw[i].v-=n;
        a.push_back(cw[i].u);
        b.push_back(cw[i].v);
        c.push_back(cw[i].c-cw[i].w);
        cnt++;
      }
    }
    printf("%d %d\n", ans,cnt);
    for(int i=0;i<cnt;++i){
      printf("%d %d %d\n", a[i],b[i],c[i]);
    }
  }
}dinic;
const int N = 805;
int n, m, p;
int vs, vt;
struct lp{
  int m,a[N],b[N];
}cw[N];
int main(){
  while(~scanf("%d%d",&p,&n)){
    vs=0;vt=2*n+1;
    dinic.init(vs,vt);
    int zero,one;
    for(int i=1;i<=n;++i){
      scanf("%d",&cw[i].m);
      zero=1;one=1;
      for(int j=0;j<p;++j){
        scanf("%d",&cw[i].a[j]);
        if(cw[i].a[j]==1)zero=0;
      }
      for(int j=0;j<p;++j){
        scanf("%d",&cw[i].b[j]);
        if(cw[i].b[j]==0)one=0;
      }
      if(zero)dinic.add_edge(vs,i,cw[i].m);
      if(one)dinic.add_edge(i+n,vt,cw[i].m);
      dinic.add_edge(i,i+n,cw[i].m);
    }
    for(int i=1;i<=n;++i){
      for(int j=1;j<=n;++j){
        if(i==j)continue;
        one=1;
        for(int h=0;h<p;++h){
          if(cw[i].b[h]+cw[j].a[h]==1)one=0;
        }
        if(one)dinic.add_edge(i+n,j,min(cw[i].m,cw[j].m));
      }
    }
    dinic.solve(n);
  }
  return 0;
}


原题目描述:

技术分享图片

POJ3436:ACM Computer Factory-最大流

标签:两台   必须   return   mat   fill   lock   ack   alt   define   

原文地址:https://www.cnblogs.com/Cwolf9/p/9419882.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!