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

来源:互联网 发布:淘宝永立旅行箱怎么样 编辑:程序博客网 时间:2024/05/16 08:21

(网络流24题大多需要spj,所以需要一个有spj的oj,本系列代码均在www.oj.swust.edu.cn测试通过)
最大权闭合子图裸题,先将所有收益加起来,源点向每个方案连接一条收益的流,每个方案向对应需要的仪器连一条INF,每个仪器向汇点连一条花费的流。
输出方案只需要在最后的阻塞流中看还剩哪几个点就好了

#include<cstdio>#include<cstdlib>#include<iomanip>#include<iostream>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>using namespace std;#define INF 100000000struct bian{    int l,r,f,lei;}a[1000000];int fir[1000000];int nex[1000000];int d[1000000];int tot=1;void add_edge(int l,int r,int f,int lei=0){    a[++tot].l=l;    a[tot].r=r;    a[tot].f=f;    a[tot].lei=lei;    nex[tot]=fir[l];    fir[l]=tot;}int s=0,t=999999;bool bfs(){    static int dui[1000000];    int top=1,my_final=2;    memset(d,-1,sizeof(d));    d[s]=0;    dui[top]=s;    while(top<my_final)    {        int u=dui[top];        for(int o=fir[u];o!=0;o=nex[o])        {            if(d[a[o].r]!=-1 || !a[o].f) continue;            dui[my_final++]=a[o].r;            d[a[o].r]=d[u]+1;            if(a[o].r==t) return true;        }        top++;    }    return false;}int dinic(int u,int flow){    if(u==t) return flow;    int left=flow;    for(int o=fir[u];o!=0&&left;o=nex[o])    {        if(d[a[o].r]==d[u]+1 && a[o].f)        {            int temp=dinic(a[o].r,min(left,a[o].f));            if(temp==0) d[a[o].r]=-1;            left-=temp;            a[o].f-=temp;            a[o^1].f+=temp;        }    }    return flow-left;}int main(){    int m,n;    scanf("%d%d",&m,&n);    int ans=0;    for(int i=1;i<=m;i++)    {        char c;        while(c<'0' || c>'9') scanf("%c",&c);        int x=0;        while(c<='9' && c>='0') x=x*10+c-'0',scanf("%c",&c);        add_edge(s,i,x,1);        add_edge(i,s,0);        ans+=x;        while(c!='\n' && c!='\r')        {            int y=0;            while(c<'0' || c>'9')            {                if(c=='\n' || c=='\r') break;                scanf("%c",&c);            }            if(c=='\n' || c=='\r') break;            while(c<='9' && c>='0') y=y*10+c-'0',scanf("%c",&c);            add_edge(i,m+y,INF);            add_edge(m+y,i,0);        }    }    for(int i=1;i<=n;i++)    {        int x;        scanf("%d",&x);        add_edge(m+i,t,x,2);        add_edge(t,m+i,0);    }    while(bfs())    {        int t=dinic(s,INF);        ans-=t;    }    for (int i=1;i<=m;i++)        if (d[i]!=-1)            printf("%d ",i);    putchar('\n');    for (int i=m+1;i<=m+n;i++)        if (d[i]!=-1)            printf("%d ",i-m);    cout<<endl;    cout<<ans<<endl;    return 0;}
0 1
原创粉丝点击