poj3436 ACM Computer Factory

来源:互联网 发布:煎饼侠 知乎 编辑:程序博客网 时间:2024/05/22 00:28

链接:http://poj.org/problem?id=3436

题意:有N台机器,输入输出都有P种配件。

输入有0,1,2,三种状态,分别代表不需要该配件,需要该配件,该配件可有可无。

输出有0,1,两种状态,分别代表该配件没有产出,该配件产出。

只有当满足某台机器的输出满足某个机器的输入时,两台机器才是完成协作。

如果一台机器的所有输出为1,且满足了它的输入,则表示产出了一台电脑。

 

参考网上思路。

拆点法。

把每个机器拆成两个点(输入点和输出点),i和i+n

建图:

如果机器的输入中没有1存在,则与源点连边,边权为INF

如果机器的输出中只有1存在,则与汇点连边,边权为INF

机器自身输入点和输出点连边,权值为这台机器的performance,即Qi

如果一台机器的输出满足另一台机器的输入,则两天机器连边,边权为INF

 

构图老是参考网上的,自己也不想想,怎么办啊~~~~这样下去怎么会有长进啊啊啊啊啊啊啊啊

 

#include<cstdio>#include<cstring>#include<queue>#define MAXN 110#define MAXP 15#define INF 0x7fffffff#define MIN(a,b) a>b?b:ausing namespace std;int map[MAXN][MAXN],mach[MAXN];  //map构建图,mach存储Qiint in[MAXN][MAXP],out[MAXN][MAXP];//存储每个机器的输入输出的配件要求int ans;int dist[MAXN];int resa[2*MAXN],resb[2*MAXN],resp[2*MAXN];int st_in(int in[][MAXP],int p,int i){   int j;   for(j=0;j<p;j++)   if(in[i][j]==1)   return 0;return 1;}int ed_out(int out[][MAXP],int p,int i){   int j;   for(j=0;j<p;j++)   if(out[i][j]!=1)   return 0;return 1;}int out_in(int out[][MAXP],int in[][MAXP],int i,int j,int p){int m;    for(m=0;m<p;m++)if((out[i][m]+in[j][m])==1)return 0;return 1;}int BFS(int st,int ed){int k,i;    memset(dist,-1,sizeof(dist));dist[st]=0;queue<int> q;q.push(st);while(!q.empty()){    k=q.front();q.pop();for(i=0;i<=ed;i++){   if(map[k][i]>0&&dist[i]<0)   {   dist[i]=dist[k]+1;   q.push(i);   }}}if(dist[ed]>0)return 1;return 0;}int DFS(int x,int ed,int low){    int i,a;if(x==ed)return low;for(i=0;i<=ed;i++){    if(map[x][i]>0&&dist[i]==dist[x]+1&&(a=DFS(i,ed,MIN(low,map[x][i])))){   map[x][i]-=a;   map[i][x]+=a;   return a;}}return 0;}void Dinic(int st,int ed){int res;while(BFS(st,ed)){   while((res=DFS(st,ed,INF)))   {   ans+=res;   }}return;}int main(){int p,n,i,j;int st,ed,cnt;while(scanf("%d%d",&p,&n)!=EOF){   memset(mach,0,sizeof(mach));   memset(map,0,sizeof(map));   memset(in,0,sizeof(in));   memset(out,0,sizeof(out));   st=0;     //超级源点   ed=2*n+1; //超级汇点   for(i=1;i<=n;i++)   {       scanf("%d",&mach[i]);   map[i][i+n]=mach[i]; //拆点,每个机器拆成输入点i和输出点i+n                        //输入点和输出点连边,权值为这台机器的performance,即Qi   for(j=0;j<p;j++)   scanf("%d",&in[i][j]);   for(j=0;j<p;j++)   scanf("%d",&out[i][j]);   if(st_in(in,p,i))   //如果机器的输入中没有1存在,则与源点连边,边权为INF   map[st][i]=INF;   if(ed_out(out,p,i))  //如果机器的输出中只有1存在,则与汇点连边,边权为INF   map[i+n][ed]=INF;   }   for(i=1;i<=n;i++)   for(j=1;j<=n;j++)   if(out_in(out,in,i,j,p))  //如果一台机器的输出满足另一台机器的输入,则两天机器连边,边权为INF   map[i+n][j]=INF;   ans=0;   cnt=0;   Dinic(st,ed);   //用Dinic求最大流   printf("%d ",ans);   for(i=1;i<=n;i++)   //在除了源点和汇点所在的边内找connection   for(j=1;j<=n;j++)   {      if(i!=j&&map[j][i+n]>0)//大于零的反向边就是我们要找的路径  {      resa[cnt]=i;  resb[cnt]=j;  resp[cnt]=map[j][i+n];  cnt++;  }   }   printf("%d\n",cnt);   for(i=0;i<cnt;i++)   printf("%d %d %d\n",resa[i],resb[i],resp[i]);}    return 0;}


 

0 0
原创粉丝点击