[网络流24题]太空飞行计划问题
题目描述
W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。实验Ej需要用到的仪器是I的子集RjÍI。配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。
对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。
题解
同样需要Ford-Fulkerson定理
源点向实验连容量为奖金的钱,实验向仪器连容量无限的边,仪器向汇点连容量为花费的边
答案同样是总奖金-最小割
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define INF 0x3f3f3f3f 6 using namespace std; 7 int n,m,cnt,tot,tmp; 8 int st,ed,ans,tp1,tp2; 9 char usd; 10 int stmt[205]; 11 bool used[205]; 12 int inst[205]; 13 bool vis[205]; 14 int cst[205]; 15 int pay[205]; 16 int dis[205]; 17 int head[205]; 18 struct Edge{ 19 int fr; 20 int to; 21 int flw; 22 int nxt; 23 }edge[10005],pth[10005]; 24 void init(){ 25 memset(head,-1,sizeof(head)); 26 } 27 void addedge(int u,int v,int f){ 28 edge[cnt].fr=u; 29 edge[cnt].to=v; 30 edge[cnt].flw=f; 31 edge[cnt].nxt=head[u]; 32 head[u]=cnt++; 33 edge[cnt].fr=v; 34 edge[cnt].to=u; 35 edge[cnt].nxt=head[v]; 36 head[v]=cnt++; 37 } 38 int bfs(int ban){ 39 queue<int>que; 40 memset(dis,0x3f,sizeof(dis)); 41 que.push(st);dis[st]=0; 42 while(!que.empty()){ 43 int u=que.front(); 44 que.pop(); 45 for(int i=head[u];i!=-1;i=edge[i].nxt){ 46 int v=edge[i].to; 47 if(!edge[i].flw||v==ban)continue; 48 if(dis[v]==0x3f3f3f3f){ 49 dis[v]=dis[u]+1; 50 que.push(v); 51 } 52 } 53 } 54 return (dis[ed]!=0x3f3f3f3f); 55 } 56 int dfs(int u,int flw,int ban){ 57 if(u==ed)return flw; 58 int All=0;int f; 59 for(int i=head[u];i!=-1;i=edge[i].nxt){ 60 int v=edge[i].to; 61 if(dis[v]!=dis[u]+1)continue; 62 if((f=dfs(v,min(flw,edge[i].flw),ban))>0){ 63 edge[i].flw-=f; 64 edge[i^1].flw+=f; 65 flw-=f;All+=f; 66 if(!flw)break; 67 } 68 } 69 return All; 70 } 71 void dinic(int ban){ 72 tmp=0; 73 memcpy(edge,pth,sizeof(edge)); 74 while(bfs(ban)){ 75 tmp+=dfs(st,INF,ban); 76 } 77 } 78 int main(){ 79 init(); 80 scanf("%d%d",&m,&n);ed=n+m+1; 81 for(int i=1;i<=m;i++){ 82 scanf("%d",&pay[i]);tot+=pay[i]; 83 usd=getchar();int tl=0; 84 while(usd!='\n'&&usd!='\r'){ 85 if(usd==' '&&tl){ 86 addedge(i,tl+m,INF); 87 tl=0;usd=getchar(); 88 continue; 89 } 90 if(usd>='0')tl=tl*10+usd-'0'; 91 usd=getchar(); 92 } 93 if(tl)addedge(i,tl+m,INF); 94 addedge(st,i,pay[i]); 95 } 96 for(int i=1;i<=n;i++){ 97 scanf("%d",&cst[i]); 98 addedge(i+m,ed,cst[i]); 99 } 100 memcpy(pth,edge,sizeof(pth)); 101 dinic(-1);ans=tmp; 102 for(int i=1;i<=n;i++){ 103 dinic(i+m); 104 if(tmp+cst[i]==ans){ 105 inst[++tp1]=i; 106 used[i]=true; 107 } 108 } 109 for(int i=1;i<=m;i++){ 110 int fl=0; 111 for(int j=head[i];j!=-1;j=edge[j].nxt){ 112 int v=edge[j].to; 113 if(!v)continue; 114 if(!used[v-m]){ 115 fl=1; 116 break; 117 } 118 } 119 if(!fl)stmt[++tp2]=i; 120 } 121 sort(stmt+1,stmt+tp2+1); 122 sort(inst+1,inst+tp1+1); 123 for(int i=1;i<=tp2;i++){ 124 printf("%d",stmt[i]); 125 if(i!=tp2)printf(" "); 126 }printf("\n"); 127 for(int i=1;i<=tp1;i++){ 128 printf("%d",inst[i]); 129 if(i!=tp1)printf(" "); 130 }printf("\n");ans=tot-ans; 131 printf("%d\n",ans); 132 return 0; 133 }