转载最小分割-最大流的通俗解释


soj 3109最小切割最大流
2010-08-31 11:33

Description



W教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。
现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。
实验Ej需要用到的仪器是I的子集Rj I。
配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。
W教授的任务是找出一个有效算法,
确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。
这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。
对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。

Input



输入包含多组测试数据,每组数据第1行有2个正整数m和n。m是实验数,n是仪器数。
接下来的m行,每行是一个实验的有关数据。
第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。
最后一行的n个数是配置每个仪器的费用。
( 1 <= m,n <= 50 )

Output



每组数据输出一行,为净收益。

Sample Input



2 3
10 1 2
25 2 3
5 6 7

Sample Output



17

Source



经典问题

#define N 105
#define inf 100000000
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int cap[N][N],pre[N];
int n,m,st,en;
bool bfs()
{
       memset(pre,-1,sizeof(pre));
       pre[st]=0;
       int q[N+10],head=0,end=1,i;
       q[0]=st;
       while(head<end)
       {
              int u=q[head++];
              for(i=0;i<=en;i++)
                     if(pre[i]==-1&&cap[u][i]>0)
                     {
                            pre[i]=u;
                            if(i==en)
                                   return 1;
                            q[end++]=i;
                     }
       }
       return 0;
}
int max_flow()
{
       int ans=0;
       while(bfs())
       {
              int minflow=inf;
              int u=en;
              while(u!=st)
              {
                     if(minflow>cap[pre[u]][u])
                            minflow=cap[pre[u]][u];
                     u=pre[u];
              }
              u=en;
              ans+=minflow;
              while(u!=st)
              {
                     cap[pre[u]][u]-=minflow;
                     cap[u][pre[u]]+=minflow;
                     u=pre[u];
              }
       }
       return ans;
}
int main()
{
       while(cin>>n>>m)
       {
              int i,j,sum=0;
              st=0;
              en=n+m+1;
              memset(cap,0,sizeof(cap));
              for(i=1;i<=n;i++)
              {
                     int get,tmp;
                     char c;
                     scanf("%d",&get);
                     sum+=get;
                     cap[i+m][en]=get;
                     while(scanf("%d%c",&tmp,&c))
                     {
                            cap[tmp][i+m]=inf;
                            if(c=='\n')
                                   break;
                     }
              }
              for(i=1;i<=m;i++)
              {
                     int cost;
                     scanf("%d",&cost);
                     cap[st][i]=cost;
              }
              printf("%d\n",sum-max_flow());
       }
       return 0;
}



来源: http://hi.baidu.com/lerroy312/blog/item/857bf51c4839f50935fa41e0.html

你可能感兴趣的:(编程,c,算法,input,任务,output)