poj 3436 ACM Computer Factory

建图题。

题意:N台机器流水作业,每台机器的输入输出各有P个参数。其中0和1分别表示不存在、存在;2表示可有可无(可以是0,也可以是1)。2只会出现在输入参数中。

分析:题目间接建图,首先设立超级源s、超级汇t。s连所有输入参数为0的机器,所有输出参数为1的机器连t。然后每台机器的输出参数与其他机器的输入参数比较,符合要求就连边。建好图后套模板就好了。注意输出要求:把能得到最大流的增广路记录下来,打印出哪两台机器相连(流水作业,有先后顺序的),以及这条边上的流。

坑:1、由于是Special Judge,只需输出一组可行解,即使是Sample,输出也可以不一样。

      2、拆点:以机器建点,把输入输出拆成两个点u、v,w就是机器的工作量。拆点之后点的数量和边的数量增加了。

      3、可恶的“2”:与s连边的要求是参数全为0,由于输入参数中有“2”这个混子,所以即使输入参数全为2,也可以与超级源s连边。

      4、数据有问题??反正我没发现。。。讨论区里说数据不足就用0代替。

View Code
  1 #include<stdio.h>
  2 #include<string.h>
  3 #define MIN(a,b) a>b?b:a
  4 #define NUM 110
  5 #define INF 0x7ffffff
  6 int map[NUM][15];
  7 typedef struct{
  8     int e,f,next;
  9 }info;
 10 info edge[NUM*NUM];
 11 int head[NUM];
 12 int Que[NUM*2];
 13 int level[NUM];
 14 int connect[1000][3]; 
 15 int N,P;
 16 int st,ed;
 17 int tol,tot;
 18 int CHECK(int a,int b)
 19 {
 20     for(int i=1;i<=P;i++)
 21     {
 22         if(map[a][i]+map[b][i]==1)return 0;   
 23     }
 24     return 1;
 25 }
 26 void Add(int s,int t,int c)
 27 {
 28     edge[tol].e=t;
 29     edge[tol].f=c;
 30     edge[tol].next=head[s];
 31     head[s]=tol++;
 32     edge[tol].e=s;
 33     edge[tol].f=0;
 34     edge[tol].next=head[t];
 35     head[t]=tol++;
 36 }
 37 int BFS()
 38 {
 39     int fr,tp,next,cur_level,cur;
 40     memset(level,-1,sizeof(level));
 41     Que[0]=st;
 42     level[st]=0;
 43     for(fr=0,tp=1;fr!=tp;fr=(fr+1))
 44     {
 45         cur=Que[fr];
 46         cur_level=level[cur];
 47         for(next=head[cur];next!=-1;next=edge[next].next)
 48         {
 49             if(edge[next].f&&level[edge[next].e]==-1){
 50                 Que[tp]=edge[next].e;
 51                 level[edge[next].e]=cur_level+1;
 52                 tp=(tp+1);
 53                 
 54             }
 55         }
 56     }
 57     return level[ed]!=-1;
 58 }
 59 int DFS(int s,int min)
 60 {
 61     int r=0,next;
 62     int t;
 63     if(s==ed)
 64         return min;
 65     for(next=head[s];r<min&&next!=-1;next=edge[next].next)
 66     {
 67         if(edge[next].f&&level[s]+1==level[edge[next].e]){
 68             t=MIN(min-r,edge[next].f);
 69             t=DFS(edge[next].e,t);
 70             if(t&&edge[next].e!=s&&(edge[next].e-s!=N&&s-edge[next].e!=N)&&(s!=st&&edge[next].e!=ed)){
 71                 connect[tot][0]=s;
 72                 connect[tot][1]=edge[next].e;
 73                 connect[tot++][2]=t; 
 74             }
 75             r+=t;
 76             edge[next].f-=t;
 77             edge[next^1].f+=t;
 78         }
 79     }
 80     if(!r)level[s]=-2;
 81     return r;
 82 }
 83 int main()
 84 {
 85     int res,t,cnt=0;
 86     int i,j,w;
 87     char str[20];
 88     while(scanf("%d%d",&P,&N)!=EOF)
 89     {
 90         for(i=0;i<N;i++)
 91         {
 92             scanf("%d",&w);
 93             
 94             map[i][0]=w;
 95             for(j=1;j<=P;j++)
 96             {
 97                 scanf("%d",&map[i][j]);    
 98             }
 99                     
100             map[i+N][0]=w;
101             for(j=1;j<=P;j++)
102             {
103                 scanf("%d",&map[i+N][j]);    
104             }
105         }
106         st=2*N;
107         ed=st+1;
108         tol=0;
109         memset(head,-1,sizeof(head));
110         for(i=0;i<N;i++)
111         {
112             for(j=1;j<=P&&map[i][j]!=1;j++){} 
113             if(j>P)Add(st,i,map[i][0]);
114         }
115         for(i=N;i<2*N;i++)
116         {
117             for(j=1;j<=P&&map[i][j];j++){}
118             if(j>P)Add(i,ed,map[i][0]);
119         }
120         for(i=0;i<N;i++)
121         {
122             Add(i,i+N,INF);
123         }
124         for(i=0;i<N;i++)
125         {
126             for(j=N;j<2*N;j++)
127             {
128                 if(CHECK(i,j))
129                     Add(j,i,MIN(map[i][0],map[j][0]));
130             }
131         }
132         res=0;
133         tot=0;
134         while(BFS())
135         {
136             while(t=DFS(st,INF))
137             {
138                 res+=t;
139             }
140         }
141         printf("%d %d\n",res,tot);
142         for(i=0;i<tot;i++)
143          {
144              printf("%d %d %d\n",connect[i][0]-N+1,connect[i][1]+1,connect[i][2]);                 
145          }
146     }
147     return 0;
148 }

 

转载于:https://www.cnblogs.com/zstu-abc/archive/2013/04/29/3050964.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值