3438: Little M's Crop
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1780 Solved: 753
[Submit][Status][Discuss]
Description
Input
Output
There is only one line, including an integer, representing the maximum gain
Range
Solution
good question~
At first, the cost flow result I thought would ask for a lot of answers. After reading the solution, I knew it was related to the minimum cut.
We take the source point as the A field and the sink point as the B field.
For crop i, if the value planted in A is a[i] and the value planted in B is b[i], then connect an edge with capacity a[i] from it to A. Similarly, connect to B. An edge of capacity b[i].
Why do you do that? Considering the last answer, one of the two sides connected by a point must be cut off. Otherwise, the point is connected to both sides, which is equivalent to planting on both sides, which does not meet the meaning of the question, so this situation does not meet the meaning of the question.
There must be one that will be cut... Hey, isn't this the smallest cut?
Then we have initially transformed the problem, that is, we have transformed the problem into the minimum cut.
Next, consider the question of composition.
In fact, the combination is also the same, that is, the combination is also divided into two parts, which are connected to A and B.
Take this set apart first. Then the incoming edge of one of the points is connected to A, and the capacity is the extra value of the combination planted in A, and the outgoing edge is connected to all the points in this combination, and the capacity is INF. B is the same.
Then we have completely transformed the problem into the minimum cut. But this question wants to make ans the biggest, what should we do?
Well, just add up the total returns and subtract the minimum cut.
Code
// By YoungNeal #include<queue> #include<cstdio> #include<cstring> #include<iostream> #define N 10005 #define inf 0x3f3f3f3f-1 you are everything; int d [N]; int cnt = 1 ; int dis [N]; int head [N]; int n, m, s, t; struct Edge{ int to,nxt,flow; }edge[4400000]; void add(int x,int y,int z){ edge[++cnt].to=y; edge[cnt].nxt=head[x]; edge[cnt].flow=z; head[x]=cnt; } bool bfs(){ memset(d,0,sizeof d); d[s]=1; std::queue<int> q; q.push(s); while(q.size()){ int u=q.front();q.pop(); for(int i=head[u];i;i=edge[i].nxt){ int to=edge[i].to; if(!edge[i].flow) continue; if(d[to]) continue; d[to]=d[u]+1; q.push(to); if(to==t) return 1; } } return 0; } int dinic(int now,int flow){ if(now==t) return flow; int rest=flow; for(int i=head[now];i;i=edge[i].nxt){ if(!rest) return flow; int to=edge[i].to; if(!edge[i].flow) continue; if(d[to]!=d[now]+1) continue; int k=dinic(to,std::min(rest,edge[i].flow)); if(!k) d[to]=0; rest-=k; edge[i].flow-=k; edge[i^1].flow+=k; } return flow-rest; } signed main(){ scanf("%d",&n); s=n+1; t=s+1; for(int x,i=1;i<=n;i++) scanf("%d",&x),tot+=x,add(s,i,x),add(i,s,0); for(int x,i=1;i<=n;i++) scanf("%d",&x),tot+=x,add(i,t,x),add(t,i,0); scanf("%d",&m); for(int i=1;i<=m;i++){ int T,tota,totb; scanf("%d%d%d",&T,&tota,&totb); tot + = tota + totb; add(s,n+2+i,tota); add(n+2+i,s,0); add(n+2+i+m,t,totb); add(t,n+2+i+m,0); for(int x,j=1;j<=T;j++){ scanf("%d",&x); add(n+2+i,x,inf); add(x,n+2+i,0); add(x,n+2+i+m,inf); add(n+2+i+m,x,0); } } int maxflow=0,flow=0; while(bfs()) while(flow=dinic(s,0x3f3f3f3f)) maxflow+=flow; printf("%d\n",tot-maxflow); return 0; }