[網路流24題]太空飛行計劃問題
阿新 • • 發佈:2018-12-17
題目描述
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 }