poj 3436 最大流

  1 /*
  2 题意:每一台computer都是有p部分组成,每一台机器都会对每台computer新加一些部分,删除一些部分,每一台机器每小时处理的computer的数量是固定的;给出的参数中,p个S表示对输入的p个部分的零件的要求:0表示必须没有,1表示必须有,2表示无所谓,p个D表示经过该机器后输出的p个部分零件的结果:0表示没有,1表示有;Q表示单位时间可处理的computer数量,最终求怎样安排这些机器的处理过程使得输出的效率最大;
  3 
  4 题解:最大流
  5 构图:将n台机器拆分成2*n个点,i->i+n表示当前机器i能处理的computer台数,然后将可以互相连接(即输入的p部分与输出的p部分需要相符合)的点连接,此处我用i+n连接j,表示机器i输出的computer可以由机器j处理,然后再加源点0,它的p部分的输出均为0,与1~n判断能否连接后再相连,权值为无限大,汇点的p部分输入均为1,n+1~2*n与汇点2*n+1判断后再相连,边权值为无限大;然后求源点到汇点的最大流即可。
  6 */
  7 #include <cstdio>
  8 #include <cstring>
  9 
 10 #define MAXN 205
 11 #define inf 1000000000
 12 
 13 int max_flow(int n,int mat[][MAXN],int source,int sink,int flow[][MAXN]){
 14     int pre[MAXN],que[MAXN],d[MAXN],p,q,t,i,j;
 15     if (source==sink) return inf;
 16     for (i=0;i<n;i++)
 17         for (j=0;j<n;flow[i][j++]=0);
 18     for (;;){
 19         for (i=0;i<n;pre[i++]=0);
 20         pre[t=source]=source+1,d[t]=inf;
 21         for (p=q=0;p<=q&&!pre[sink];t=que[p++])
 22             for (i=0;i<n;i++)
 23                 if (!pre[i] && (j=mat[t][i]-flow[t][i]))
 24                     pre[que[q++]=i]=t+1,d[i]=d[t]<j?d[t]:j;
 25                 else if (!pre[i]&&(j=flow[i][t]))
 26                     pre[que[q++]=i]=-t-1,d[i]=d[t]<j?d[t]:j;
 27         if (!pre[sink]) break;
 28         for (i=sink;i!=source;)
 29             if (pre[i]>0)
 30                 flow[pre[i]-1][i]+=d[sink],i=pre[i]-1;
 31             else
 32                 flow[i][-pre[i]-1]-=d[sink],i=-pre[i]-1;
 33     }
 34     for (j=i=0;i<n; j+=flow[source][i++]);
 35     return j;
 36 }
 37 
 38 struct node
 39 {
 40     int q;
 41     int s[11],d[11];
 42 }nodes[55];
 43 
 44 int p;
 45 
 46 bool match(node a, node b)
 47 {
 48     for(int i=0; i<p; i++)
 49         if (a.d[i] != b.s[i] && b.s[i] != 2)
 50             return false;
 51     return true;
 52 }
 53 
 54 int main(void)
 55 {
 56     int n;
 57     int mat[MAXN][MAXN];
 58     int flow[MAXN][MAXN];
 59     while (~scanf("%d%d",&p,&n))
 60     {
 61         memset(mat,0,sizeof(mat));
 62         for(int i=1; i<=n; i++)
 63         {
 64             scanf("%d",&nodes[i].q);
 65             mat[i][i+n] = nodes[i].q; // 拆点
 66             for(int j=0; j<p; j++)
 67                 scanf("%d",&nodes[i].s[j]);
 68             for(int j=0; j<p; j++)
 69                 scanf("%d",&nodes[i].d[j]);
 70         }
 71         
 72         for(int i=0; i<p; i++)
 73         {
 74             nodes[0].d[i] = 0;
 75             nodes[n+1].s[i] = 1;
 76         }
 77 
 78         for(int i=1; i<=n; i++)
 79         {
 80             if (match(nodes[0],nodes[i]))
 81                 mat[0][i] = 10005;
 82             if (match(nodes[i],nodes[n+1]))
 83                 mat[i+n][2*n+1] = 10005;
 84         }
 85         for(int i=1; i<=n; i++)
 86             for(int j=1; j<=n; j++)
 87                 if (i != j && match(nodes[i],nodes[j]))
 88                     mat[i+n][j] = nodes[i].q;
 89 
 90         printf("%d ",max_flow(2*n+2,mat,0,2*n+1,flow));
 91 
 92         int sum = 0;
 93         for(int i=1; i<=n; i++)
 94             for(int j=1; j<=n; j++)
 95                 if (flow[i+n][j])
 96                     sum++;
 97         printf("%d\n",sum);
 98         for(int i=1; i<=n; i++)
 99             for(int j=1; j<=n; j++)
100                 if (flow[i+n][j] > 0)
101                     printf("%d %d %d\n",i,j,flow[i+n][j]);
102     }
103     return 0;
104 }

 

posted @ 2014-04-16 21:18  辛力啤  阅读(197)  评论(0编辑  收藏  举报