[网络流24题] 太空飞行计划问题

这道题目的核心是模型转化

将题意反过来考虑,变成“要求选出一个实验的集合,那么这个集合所附带的器材必须选,求最大点权和”

转化为最大权闭合子图

做法:

从源点向每一个实验连边,容量为实验的收益

每个实验和它依赖的仪器之间连inf边

从仪器向汇点连边,容量为仪器费用

跑S-T最大流,用实验的总收益减去最大流的值就是最大收益

具体方案的输出,在最后一次分层图bfs(就是没到达汇点的那次)中访问过的点就是选要择的

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 1e9
using namespace std;
char tmpch;
inline int read(){
    int re=0,flag=1;char ch=tmpch;
    //if(ch=='
'||ch=='
') exit(0);
    while(ch>'9'||ch<'0'){
        /*cout<<"useless char "<<(int)ch<<"
";*/
        /*if((int)ch==-1) exit(0); */
        if(ch=='-') flag=-1; 
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
    tmpch=ch;
    //cout<<"read in "<<re*flag<<"
";
    return re*flag;
}
int n,m,cnt=-1,ans=0,first[110],cur[110],dep[110];
struct edge{
    int to,next,w;
}a[10010];
inline void add(int u,int v,int w){
    //cout<<"add "<<u<<" "<<v<<" "<<w<<"
";
    a[++cnt]=(edge){v,first[u],w};first[u]=cnt;
    a[++cnt]=(edge){u,first[v],0};first[v]=cnt;
}
bool bfs(int s,int t){
    int i,u,v,q[110],head=0,tail=1;
    for(i=s;i<=t;i++) dep[i]=-1,cur[i]=first[i];
    dep[s]=0;q[0]=s;
    while(head<tail){
        u=q[head++];
        //cout<<"bfs "<<u<<" "<<dep[u]<<"
";
        for(i=first[u];~i;i=a[i].next){
            v=a[i].to;
            if(~dep[v]||!a[i].w) continue;
            dep[v]=dep[u]+1;q[tail++]=v;
        }
    }
    return ~dep[t];
}
int _min(int l,int r){return (l<r)?l:r;}
int dfs(int u,int t,int limit){
    if(u==t||!limit) return limit;
    int i,v,f,flow=0;
    for(i=first[u];~i;i=a[i].next){
        v=a[i].to;
        if((dep[v]==dep[u]+1)&&(f=dfs(v,t,_min(limit,a[i].w)))){
            flow+=f;limit-=f;
            a[i].w-=f;a[i^1].w+=f;
            if(!limit) return flow;
        }
    }
    return flow;
}
void dinic(int s,int t){
    while(bfs(s,t)) ans+=dfs(s,t,inf);
}
int main(){
    freopen("shuttle.in","r",stdin);
    freopen("shuttle.out","w",stdout);
    memset(first,-1,sizeof(first));
    int i,t1,sum=0;
    n=read();m=read();tmpch=0;
    for(i=1;i<=n;i++){
        t1=read();add(0,i,t1);sum+=t1;
        tmpch=0;
        //cout<<"experiment "<<i<<"
";
        while(((t1=read())||1)&&tmpch!='
'&&tmpch!='
') add(i,n+t1,inf);
        tmpch=0;add(i,n+t1,inf);
    }
    //cout<<"finish experiment
";
    for(i=1;i<=m;i++) t1=read(),add(n+i,m+n+1,t1);
    //cout<<"finish read in
";tmpch=0;
    dinic(0,n+m+1);
    for(i=1;i<=n;i++) if(~dep[i]) printf("%d ",i);printf("
");
    for(i=1;i<=m;i++) if(~dep[n+i]) printf("%d ",i);printf("
");
    printf("%d
",sum-ans);
    return 0;
}
原文地址:https://www.cnblogs.com/dedicatus545/p/8398392.html