【网络流24题】 太空飞行计划问题

题目

LibreOJ

题解

关于题意,并不是很清楚一个实验如果不赚不亏要不要选 (spj是因为这个地方吗???)

建图就是将所有实验与源点相连,容量为收益;所有仪器与汇点相连,容量为价格;再将实验与所需仪器相连,容量为inf;将所有实验的收益相加减去跑出的最大流,得到的就是净收益

至于记录方案,我也不是很懂,可以看看[http://blog.csdn.net/slyz_wumingshi/article/details/62228040](http://blog.csdn.net/slyz_wumingshi/article/details/62228040

代码

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#define N 40005
#define inf 2000000000
#define ll long long
using namespace std;

int m,n,s,t,ans[N]; 
ll sum,cost;
bool flag[N];

struct node
{
    int to,nt;
    ll cap;
}E[N];

int num=1,p[N];
void add(int x,int y,ll v)
{
    E[++num].to=y;E[num].cap=v;
    E[num].nt=p[x];p[x]=num;
    E[++num].to=x;E[num].cap=0;
    E[num].nt=p[y];p[y]=num;
}

int d[N],q[N];
bool bfs()
{
    memset(d,-1,sizeof(d));
    int head=0,tail=0;
    q[++tail]=s;d[s]=0;
    while(head<tail)
    {
        int k=q[++head];
        for(int e=p[k];e;e=E[e].nt)
        {
            int kk=E[e].to;
            if(d[kk]==-1&&E[e].cap)
            {
                d[kk]=d[k]+1;
                q[++tail]=kk;
                flag[kk]=1;
            }
        }
    }
    return d[t]>=0;
}

ll dfs(int x,ll f)
{
    memset(flag,0,sizeof(flag));
	if(x==t) return f;
    for(int e=p[x];e;e=E[e].nt)
    {
        int k=E[e].to;
        if(d[k]==d[x]+1&&E[e].cap)
        {
            ll ff=dfs(k,min(E[e].cap,f));
            if(ff)
            {
                E[e].cap-=ff;
                E[e^1].cap+=ff;
                return ff;
            }
        }
    }
    return 0;
}

int main()
{
    scanf("%d%d",&m,&n);
    s=0;t=m+n+1;
    for(int i=1;i<=m;i++)
    {
        int v,x=0;scanf("%d",&v);
        add(s,i,v);sum+=v;
        char ch;scanf("%c",&ch);
        while(ch!=10)
        {
            if(ch==' ')
            {
                if(x) add(i,x+m,inf),x=0;
            }
            else x=x*10+ch-'0';
            scanf("%c",&ch);
        }
        add(i,x+m,inf);
    }
    for(int i=1;i<=n;i++)
    {
        int c;scanf("%d",&c);
        add(m+i,t,c);
    }
    while(bfs())
    {
        ll f;
        while(f=dfs(s,inf)) cost+=f;
    }
    for(int i=1;i<=m;i++)
      if(flag[i]) printf("%d ",i);
    printf("
");ans[0]=0;
    for(int i=m+1;i<=m+n;i++)
      if(flag[i]) printf("%d ",i-m);
    printf("
%lld",sum-cost);
    return 0;
}