建图:源点—(w[i])—>实验—(∞)—>仪器—(cost[i])—>汇点,
如果该实验造成收益,则仪器到汇点的边在最小割中,
如果该实验造成损失,则源点到实验的边在最小割中,
故答案就是所有实验的所有收益(不考虑仪器花费的)减去最小割。
特别注意,最后统计方案时,不能直接判断边权是否为0,因为当花费等于收益时,这种方法会将该实验计入答案而题目则不允许,故应该在最后Bfs出的level数组中判断是否可达,再通过实验把所需仪器统计出来。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cmath> 6 #include <ctime> 7 #include <algorithm> 8 #include <queue> 9 #include <vector> 10 11 using namespace std; 12 13 template<const int _n> 14 struct Edge 15 { 16 struct Edge_base { int to,next,w; }e[_n]; 17 int p[_n],cnt; 18 Edge() { clear(); } 19 inline int start(const int x) { return p[x]; } 20 inline void insert(const int x,const int y,const int z) 21 { e[++cnt].to=y; e[cnt].next=p[x]; e[cnt].w=z; p[x]=cnt; return ; } 22 inline Edge_base& operator[](const int x) { return e[x]; } 23 inline void clear() { cnt=1,memset(p,0,sizeof(p)); } 24 }; 25 26 int n,m,SSS,TTT; 27 int w[210],cost[210]; 28 int level[210],cur[210]; 29 char str[11000]; 30 Edge<25000> e; 31 vector<pair<int,int> > vec; 32 33 bool Bfs(const int S) 34 { 35 int i,t; 36 queue<int> Q; 37 memset(level,0,sizeof(int)*(n+m+3)); 38 level[S]=1;Q.push(S); 39 while(!Q.empty()) 40 { 41 t=Q.front(),Q.pop(); 42 for(i=e.start(t);i;i=e[i].next) 43 { 44 if(!level[e[i].to] && e[i].w) 45 { 46 level[e[i].to]=level[t]+1; 47 Q.push(e[i].to); 48 } 49 } 50 } 51 return level[TTT]; 52 } 53 54 int Dfs(const int S,const int bk) 55 { 56 if(S==TTT)return bk; 57 int rest=bk; 58 for(int &i=cur[S];i;i=e[i].next) 59 { 60 if(level[e[i].to]==level[S]+1 && e[i].w) 61 { 62 int flow=Dfs(e[i].to,min(rest,e[i].w)); 63 e[i].w-=flow; 64 e[i^1].w+=flow; 65 if((rest-=flow)<=0)break; 66 } 67 } 68 69 if(rest==bk)level[S]=0; 70 return bk-rest; 71 } 72 73 int Dinic() 74 { 75 int i,j,flow=0; 76 int Ans[210]={0}; 77 while(Bfs(SSS)) 78 { 79 memcpy(cur,e.p,sizeof(int)*(n+m+3)); 80 flow+=Dfs(SSS,0x3f3f3f3f); 81 } 82 83 for(i=1;i<=n;++i) 84 { 85 if(level[i]) 86 { 87 printf("%d ",i); 88 for(j=e.start(i);j;j=e[j].next) 89 Ans[e[j].to-n]=1; 90 } 91 } 92 printf("\n"); 93 for(i=1;i<=m;++i) 94 { 95 if(Ans[i])printf("%d ",i); 96 } 97 printf("\n"); 98 99 return flow; 100 } 101 102 void Build() 103 { 104 int i; 105 SSS=n+m+1,TTT=n+m+2; 106 for(i=1;i<=n;++i) 107 { 108 e.insert(SSS,i,w[i]); 109 e.insert(i,SSS,0); 110 } 111 for(i=0;i<(int)vec.size();++i) 112 { 113 e.insert(vec[i].first,vec[i].second+n,0x3f3f3f3f); 114 e.insert(vec[i].second+n,vec[i].first,0); 115 } 116 for(i=n+1;i<=m+n;++i) 117 { 118 e.insert(i,TTT,cost[i-n]); 119 e.insert(TTT,i,0); 120 } 121 return ; 122 } 123 124 #define EOL -1 125 int getint(int& data,int & t) 126 { 127 char ch;data=0; 128 ch=str[t++]; 129 while((ch<'0' || ch>'9') && ch)ch=str[t++]; 130 while(ch>='0' && ch<='9')data=data*10+ch-48,ch=str[t++]; 131 if(!data)return EOL; 132 return 1; 133 } 134 135 int main() 136 { 137 freopen("shuttle.in","r",stdin); 138 freopen("shuttle.out","w",stdout); 139 140 int i,c,Sum=0; 141 142 scanf("%d%d",&n,&m); 143 for(i=1;i<=n;++i) 144 { 145 scanf("%d",&w[i]); 146 Sum+=w[i]; 147 fgets(str,10000,stdin); 148 int t=0; 149 while(~getint(c,t)) 150 { 151 vec.push_back(make_pair(i,c)); 152 if(t==-1)break; 153 } 154 } 155 for(i=1;i<=m;++i) 156 { 157 scanf("%d",&cost[i]); 158 } 159 160 Build(); 161 162 printf("%d\n",Sum-Dinic()); 163 164 return 0; 165 }