zoukankan      html  css  js  c++  java
  • 【最大流】POJ3236-ACM Computer Factory

    【题意】

    装配一个电脑需要P个零件,现在给出N机器的信息,每个机器可以将k个电脑由状态{S1,S2..,Sp}转变为{Q1,Q2..,Qp},问最多能装配多少台电脑以及对应的方案?

    【思路】

    1A..拆点,将每个机器状态S到状态Q的容量设为k,其余的设为INF。设置{0,0,0}(或含有2)和源点连接,{1,1,1}(或含有2)和汇点连接。用Dinic跑一次最大流,反向边最后的容量就是方案。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<cstdlib>
      7 #include<vector>
      8 #include<cmath>
      9 #include<queue>
     10 using namespace std;
     11 struct node 
     12 {
     13     int to,pos,cap;
     14 };
     15 const int MAXN=55;
     16 const int MAXP=15;
     17 const int MAXM=130;
     18 const int INF=0x7fffffff;
     19 int n,p;
     20 int s[MAXN][MAXP],q[MAXN][MAXP],value[MAXN];
     21 int vis[MAXM];
     22 vector<node> E[MAXM*MAXM];
     23 int dis[MAXM];
     24 int flow;
     25 
     26 void addedge(int u,int v,int w) 
     27 {
     28     /*
     29     POJ必须写成如下形式才能A,否则会CE 
     30     node tmp;
     31     tmp.to=v;
     32     tmp.pos=E[v].size();
     33     tmp.cap=w;
     34     E[u].push_back(tmp);
     35     tmp.to=u;
     36     tmp.pos=E[u].size()-1;
     37     tmp.cap=0;
     38     E[v].push_back(tmp);
     39     */
     40     E[u].push_back((node){v,E[v].size(),w});
     41     E[v].push_back((node){u,E[u].size()-1,0});
     42 }
     43 
     44 void init() 
     45 {
     46     scanf("%d%d",&p,&n) ;
     47     for (int i=0; i<n; i++) 
     48     {
     49         scanf("%d",&value[i]);
     50         for (int j=0; j<p; j++) 
     51             scanf("%d",&s[i][j]);
     52         for (int j=0; j<p; j++) 
     53             scanf("%d",&q[i][j]);
     54     }
     55 }
     56 
     57 void buildup() 
     58 {
     59     /*拆点*/
     60     for (int i=0; i<n; i++)
     61         addedge(i*2+1,i*2+2,value[i]);
     62 
     63     /*如果流入全为0或2,则与源点相连*/
     64     for (int i=0; i<n; i++) 
     65     {
     66         int flag=1;
     67         for (int j=0; j<p; j++) if (s[i][j]==1) 
     68         {
     69                 flag=0;
     70                 break;
     71         }
     72         if (flag) addedge(0,i*2+1,INF);
     73     }
     74 
     75     /*如果流出全为1或2,则与汇点相连*/
     76     for (int i=0; i<n; i++) 
     77     {
     78         int flag=1;
     79         for (int j=0; j<p; j++) if (q[i][j]==0)
     80         {
     81                 flag=0;
     82                 break;
     83         }
     84         if (flag) addedge(i*2+2,n*2+1,INF);
     85     }
     86 
     87     /*连边*/
     88     for (int i=0; i<n; i++)
     89         for (int j=0; j<n; j++) 
     90         {
     91             int flag=1;
     92             for (int k=0; k<p; k++)
     93                 if ((q[i][k]==1 && s[j][k]==0) || (q[i][k]==0 && s[j][k]==1)) 
     94                 {
     95                     flag=0;
     96                     break;
     97                 }
     98             if (flag) addedge(i*2+2,j*2+1,INF);
     99         }
    100 }
    101 
    102 int bfs() 
    103 {
    104     memset(dis,-1,sizeof(dis));
    105     queue<int> que;
    106     que.push(0);
    107     dis[0]=0;
    108 
    109     while (!que.empty()) 
    110     {
    111         int head=que.front();
    112         que.pop();
    113         for (int i=0; i<E[head].size(); i++) 
    114         {
    115             node tmp=E[head][i];
    116             if (dis[tmp.to]!=-1 || tmp.cap<=0) continue;
    117             dis[tmp.to]=dis[head]+1;
    118             que.push(tmp.to);
    119         }
    120     }
    121     if (dis[2*n+1]==-1) return 0;
    122     else return 1;
    123 }
    124 int dfs(int s,int t,int f)
    125 {
    126     int ret=0;
    127     if (s==t) return f;
    128     vis[s]=1;//不要忘记这里要设置为访问过 
    129     for (int i=0;i<E[s].size();i++)
    130     {
    131         node &tmp=E[s][i]; 
    132         if (vis[tmp.to]==0 && tmp.cap>0)
    133         {
    134             int delta=dfs(tmp.to,t,min(tmp.cap,f));
    135             if (delta>0)
    136             {
    137                 ret+=delta;
    138                tmp.cap-=delta;
    139                E[tmp.to][tmp.pos].cap+=delta;
    140                f-=delta; 
    141             }
    142         }
    143     }
    144     return ret;
    145 }
    146 
    147 void Dinic() 
    148 {
    149     flow=0;
    150     while (bfs()) 
    151     {
    152         for (;;) 
    153         {
    154             memset(vis,0,sizeof(vis));
    155             int f=dfs(0,2*n+1,INF);
    156             if (f==0) break;
    157             else flow+=f;
    158         }
    159     }
    160 }
    161 
    162 void output() 
    163 {
    164     cout<<flow<<' ';
    165     int M=0,l[MAXN],r[MAXN],c[MAXN];
    166     for (int i=1; i<2*n+1; i++)
    167         for (int j=0; j<E[i].size(); j++) 
    168         {
    169             node tmp=E[i][j];
    170             if (E[tmp.to][tmp.pos].cap>0 && E[tmp.to][tmp.pos].cap<=flow && tmp.to!=2*n+1 && ((tmp.to+1)>>1!=(i+1)>>1)) 
    171             {
    172                 M++;
    173                 l[M]=(i+1)>>1;
    174                 r[M]=(tmp.to+1)>>1;
    175                 c[M]=E[tmp.to][tmp.pos].cap;
    176             }
    177         }
    178     cout<<M<<endl;
    179     for (int i=1; i<=M; i++) cout<<l[i]<<' '<<r[i]<<' '<<c[i]<<endl;
    180 }
    181 
    182 int main()
    183 {
    184         init();
    185         buildup();
    186         Dinic();
    187         output();
    188         return 0;
    189 }
  • 相关阅读:
    两台oracle数据库相互导数据(转载)
    resin之jvm优化
    求一表中每一个类别共有几条记录数
    jQuery+Ajax+Struts2.0
    改进nginx访问resin的性能
    通过web修改squid用户上网密码
    jvm优化
    Samba通过ad域进行认证并限制空间大小
    Samba 与squid 都可以统一使用域(AD)验证
    ASP.NET 下载文件
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5159845.html
Copyright © 2011-2022 走看看