swust1737: 太空飞行计划问题
2016-07-13 14:50
423 查看
链接:http://www.oj.swust.edu.cn/problem/show/1737
题意:中文题。
分析:网络流24题第二题。对每个实验加一条容量为经费的边与超级源相连,对每个仪器加一条容量为花费的边与超级汇相连。每个项目和对应的仪器直接连一条容量为无穷大的边。然后我们跑dinic是求出的最小割,然后我们将总的经费减去最小割(费用总和)就能得到最大收益啦。输出的时候有个点:我们直接输出bfs中最后一遍标记过的点,因为到了最后还剩下容量没跑完的点就是收益的经费。
代码:
#include<map> #include<set> #include<cmath> #include<queue> #include<bitset> #include<math.h> #include<vector> #include<string> #include<sstream> #include<stdio.h> #include<cstring> #include<iostream> #include<algorithm> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int N=155; const int MAX=1000000100; const int mod=100000000; const int MOD1=1000000007; const int MOD2=1000000009; const double EPS=0.00000001; typedef long long ll; const ll MOD=998244353; const int INF=1000000010; const double pi=acos(-1.0); typedef double db; typedef unsigned long long ull; int tot,u ,v[N*N],cap[N*N],flow[N*N],pre[N*N]; void add(int a,int b,int c,int f) { v[tot]=b;cap[tot]=c;flow[tot]=f;pre[tot]=u[a];u[a]=tot++; } bool q ; int d ,dis ,head ; bool bfs(int a,int b) { int i,l=1,r=1; memset(q,0,sizeof(q)); d[1]=a;q[a]=1;dis[a]=0; for (;l<=r;l++) for (i=u[d[l]];i!=-1;i=pre[i]) if (!q[v[i]]&&cap[i]>flow[i]) q[v[i]]=1,d[++r]=v[i],dis[v[i]]=dis[d[l]]+1; return q[b]; } int dfs(int a,int b,int en) { if (a==en||b==0) return b; int ret=0,f; for (int& i=u[a];i!=-1;i=pre[i]) if (dis[v[i]]==dis[a]+1&&(f=dfs(v[i],min(b,cap[i]-flow[i]),en))>0) { flow[i]+=f;flow[i^1]-=f; b-=f;ret+=f; if (b==0) break ; } return ret; } string str; int main() { int a,b,i,n,m,sum=0,ans=0; scanf("%d%d", &n, &m); tot=0;memset(u,-1,sizeof(u)); for (i=1;i<=n;i++) { scanf("%d", &a); sum+=a;add(0,i,a,0);add(i,0,0,0); getline(cin,str); istringstream ssin(str); while (ssin>>a) { add(i,a+n,INF,0);add(a+n,i,0,0); } } for (i=1;i<=m;i++) { scanf("%d", &a); add(n+i,n+m+1,a,0);add(n+m+1,n+i,0,0); } for (i=0;i<=n+m+1;i++) head[i]=u[i]; while (bfs(0,n+m+1)) { ans+=dfs(0,INF,n+m+1); for (i=0;i<=n+m+1;i++) u[i]=head[i]; } for (i=1;i<=n;i++) if (q[i]) printf("%d ", i); printf("\n"); for (i=n+1;i<=n+m;i++) if (q[i]) printf("%d ", i-n); printf("\n"); printf("%d\n", sum-ans); return 0; }
相关文章推荐