POJ-3436 拆点做最大流

原创 2012年03月26日 23:13:28

      这道题好长..看了好久才看懂..囧..也就是说每个machine对于电脑半成品所包含零件的输入有三种要求..0代表不能有该零件输入..1代表必须有该零件输入..2代表有或没有无所谓...而每个machine产生的电脑半成品中每个零件有两种状态..0代表半成品包含该零件,1代表半成品不包含该零件..题目中最开始是给一堆没有任何零件的半成品..最终需要的是所有零件都包含的成品..问最多能得到多少成品电脑..

      建立一个超级源点,其所有的s[]为0,Q为无穷大..建立一个超级汇点,其所有的d[]为1,Q为无穷大...将所有的点拆成汇点和出点,汇点到出点的流量为其Q..一个machine的结果满足另一个machine的输入的建立有向线段...在这个过程中超级源点和超级汇点都参与..

     从超级源点到超级汇点跑最大流..最大流的结果就是输出的最多成品电脑数..

     而要得出用了哪些路径,每条路径流过的流量.那么就判断输入时的那些个个machine间的有向线段剩余容量的变化..


Program:

#include<iostream>
#include<string.h>
#include<math.h>
#include<stdio.h>
#include<queue>
#define oo 2000000000
using namespace std;
struct node1
{
      int Q,s[11],d[11];
}machine[55];
struct node2
{
      int x,y,c,next;
}line[20005];
int n,p,m,_link[205],ans,num,way[505],dis[205];
bool inqueue[205];
queue<int> myqueue;
bool BFS()
{
      int h,k;
      while (!myqueue.empty()) myqueue.pop();
      memset(dis,0,sizeof(dis));
      dis[0]=1;
      myqueue.push(0);
      while (!myqueue.empty())
      {
            h=myqueue.front();
            myqueue.pop();
            k=_link[h];
            while (k)
            {
                  if (line[k].c && !dis[line[k].y])
                  {
                         dis[line[k].y]=dis[h]+1;
                         myqueue.push(line[k].y);
                  }
                  k=line[k].next;
            }
      }
      return dis[n];
}
bool DFS(int p,int Flow)
{
      int k;
      if (p==n)
      {
            ans+=Flow;
            for (k=1;k<=num;k++)
            {
                   line[way[k]].c-=Flow; 
                   m++;
                   line[m].c=Flow;
                   line[m].x=line[way[k]].y;
                   line[m].y=line[way[k]].x;
                   line[m].next=_link[line[m].x];
                   _link[line[m].x]=m;
            }
            return true;
      }
      num++;
      k=_link[p];
      while (k)
      {
            if (line[k].c && dis[line[k].y]-dis[p]==1)
            {
                  way[num]=k;
                  if (DFS(line[k].y,min(Flow,line[k].c))) return true;
            }
            k=line[k].next;
      }
      num--;
      return false;
}
void MaxFlow()
{
      ans=0;
      while (BFS())
      {
            num=0;
            DFS(0,oo);
      }
      return;
}
int main()
{
      int i,j,k,h;
      scanf("%d%d",&p,&n);
      memset(machine,0,sizeof(machine));
      memset(_link,0,sizeof(_link));
      for (i=1;i<=n;i++)
      {
             scanf("%d",&machine[i].Q);
             for (j=1;j<=p;j++) scanf("%d",&machine[i].s[j]);
             for (j=1;j<=p;j++) scanf("%d",&machine[i].d[j]);
      }
      n++;
      machine[0].Q=machine[n].Q=oo; 
      for (j=1;j<=p;j++) machine[n].s[j]=1;
      m=0;
      for (i=1;i<=n;i++)
      {
            m++;
            line[m].x=i*2-1; line[m].y=i*2; line[m].c=machine[i].Q;
            line[m].next=_link[line[m].x];
            _link[line[m].x]=m;
      } 
      for (i=0;i<n;i++)
         for (j=1;j<=n;j++)
         if (i!=j)
         {
               if (!i && j==n) continue;
               for (k=1;k<=p;k++)
                 if (machine[j].s[k]==1 && !machine[i].d[k] ||
                       !machine[j].s[k] &&  machine[i].d[k]) goto A;
               m++;
               line[m].x=i*2; line[m].y=j*2-1; line[m].c=oo;
               line[m].next=_link[line[m].x];   
               _link[line[m].x]=m;
               A: ;
         }
      n*=2;
      h=m;
      MaxFlow();
      num=0;
      for (i=n/2+1;i<=h;i++)
        if (line[i].c!=oo && line[i].x!=0 && line[i].y!=n-1)
            way[++num]=i; 
      printf("%d %d\n",ans,num);
      for (i=1;i<=num;i++) 
        printf("%d %d %d\n",line[way[i]].x/2,line[way[i]].y/2+1,oo-line[way[i]].c);
      return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

UVA - 1658(网络流经典拆点方法)

把每个点(除了1,n)之外拆成i和i1,两点间连一条容量为1,费用为零的边,这样可以限定,每个点只被跑到一次,那么之后跑一个最流量为2的最小费用流就可以了。 至于其他边,流量设为1,保证每个边只被跑...
  • playwfun
  • playwfun
  • 2015年09月10日 21:36
  • 617

TYVJ 1935 拆点网络流

思路: 就是一个多重匹配 把每个防御塔拆成 拆成第j次 发射的导弹 跑个网络流//By SiriusRen #include #include #include #include #in...
  • qq_31785871
  • qq_31785871
  • 2016年12月22日 17:08
  • 499

ZOJ3460 Missile 二分图(拆点)+二分

这个题其实就是n个塔,每个塔最多发射m次火箭,击中m个目标,每个塔只能同时发射一枚火箭准备时间是t1s,发射时间是t2min,注意单位,这块比较坑,然后塔和目标分成两个集合建立二分图,把塔拆点成m个,...
  • zcmartin2014214283
  • zcmartin2014214283
  • 2016年04月28日 22:16
  • 248

poj3698(二分图最大匹配 + 拆点)

思路:把电影拆开,,,对于每部电影的去的天数呢分开,,(1...d1)(d1 + 1.....d1 + d2)....入上面这种拆点。 然后就是每周的周几可以去,就把周扩展成天:比如说1表示第一周的...
  • KIJamesQi
  • KIJamesQi
  • 2015年09月25日 11:50
  • 296

zoj3460(二分图,拆点,二分)

Description You control N missile launching towers. Every tower has enough missiles, but for each t...
  • martinue
  • martinue
  • 2016年04月25日 21:06
  • 276

zoj3460(二分图,拆点,二分)

Description You control N missile launching towers. Every tower has enough missiles, but for ea...
  • yuanjunlai141
  • yuanjunlai141
  • 2016年04月27日 19:41
  • 376

POJ 3686 The Windy's (二分图最小权匹配 拆点 构图)

题意: 有n个订单m个车间,每个车间均可以单独完成任何一个订单。每个车间完成不同订单的时间是不同的。不会出现两个车间完成同一个订单的情况。给出每个订单在某个车间完成所用的时间。问订单完成的平均时间...
  • CillyB
  • CillyB
  • 2017年05月04日 16:11
  • 171

BZOJ-1877 晨跑 最小费用最大流+拆点

其实我是不想做这种水题的QWQ,没办法,剧情需要 1877: [SDOI2009]晨跑 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 1704 S...
  • DaD3zZ
  • DaD3zZ
  • 2016年03月16日 19:51
  • 420

hdu 4289 Control(网络流 最大流+拆点)(模板)

hdu 4289 Control(网络流 最大流+拆点)(模板)
  • u012860063
  • u012860063
  • 2014年08月09日 22:04
  • 1093

Codevs_P1227 方格取数2(拆点网络流+最小费用流)

时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij ...
  • qq_18455665
  • qq_18455665
  • 2015年12月31日 19:44
  • 323
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ-3436 拆点做最大流
举报原因:
原因补充:

(最多只允许输入30个字)