P2762 太空飞行计划问题(网络流24题之一) 最大权闭合子图

版权声明:本博客内容基本为原创,如有问题欢迎联系,未经允许请勿转载 https://blog.csdn.net/qq_41955236/article/details/82024924

题目描述

W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。实验Ej需要用到的仪器是I的子集RjÍI。配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。

对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。

输入输出格式

输入格式:

第1行有2 个正整数m和n。m是实验数,n是仪器数。接下来的m 行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。最后一行的n个数是配置每个仪器的费用。

输出格式:

第1 行是实验编号;第2行是仪器编号;最后一行是净收益。

输入输出样例

输入样例:

2 3
10 1 2
25 2 3
5 6 7

输出样例:

1 2
1 2 3
17

最大权闭合子图模板题,不解释了。


代码如下:

       

#include <stdio.h>
#include <algorithm>
#include <queue>
#include <string.h>
#include <math.h>
#include <iostream>
#include <math.h>
using namespace std;
typedef long long ll;
const int N = 505;
const int inf = 999999999;
struct Edge{
    int v,next;
    int w;
}edge[N*N];
int head[N];
int level[N];
int tot,now,n,m;
vector<int> exper,tool;
void init(){
    memset(head,-1,sizeof(head));
    tot=0; exper.clear(); tool.clear();
}
void add(int u,int v,int w){
    edge[tot].v=v,edge[tot].w=w,edge[tot].next=head[u],head[u]=tot++;
    edge[tot].v=u,edge[tot].w=0,edge[tot].next=head[v],head[v]=tot++;
}
int BFS(int sp,int tp){
    queue<int >q;
    memset(level,0,sizeof(level));
    level[sp]=1;
    q.push(sp);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        if(u==tp) return 1;
        for(int k=head[u];k!=-1;k=edge[k].next){
            int v=edge[k].v;
            int w=edge[k].w;
            if(level[v]==0&&w!=0){
                level[v]=level[u]+1;
                q.push(v);
            }
        }
    }
    return -1;
}
int dfs(int u,int tp,int increaseRoad){
    if(u==tp) return increaseRoad;
    int ret=0;
    for(int k=head[u];k!=-1;k=edge[k].next){
        int v=edge[k].v;
        int w=edge[k].w;
        if(level[v]==level[u]+1&&w!=0){
            int MIN=min(increaseRoad-ret,w);
            w=dfs(v,tp,MIN);
            edge[k].w-=w;
            edge[k^1].w+=w;
            ret+=w;
            if(ret==increaseRoad) return ret;
        }
    }
    return ret;
}
ll Dinic(int sp,int tp){
    ll ans = 0;
    while(BFS(sp,tp)!=-1) ans+=(ll)dfs(sp,tp,inf*1.0);
    return ans;
}
int ans=0;
bool vis[N];
void dfs(int u){
    if(u>=1&&u<=n) exper.push_back(u);
    if(u>n) tool.push_back(u-n);
    vis[u]=true;
    for(int k=head[u];k!=-1;k=edge[k].next){
        if(edge[k].w>0&&!vis[edge[k].v]){
            dfs(edge[k].v);
        }
    }
}
int main(){
    int x,y;
    while(scanf("%d%d",&n,&m)!=EOF){
        init();
        int sp=0,tp=n+m+1;
        ll sum=0;
        for(int i=1;i<=n;i++){
            int w;
            scanf("%d",&w);
            add(sp,i,w),sum+=w;
            char ch=getchar();
            while((ch=getchar())!='\n')
            {
                x=ch-'0';
                while((ch=getchar())&&ch>='0'&&ch<='9')
                    x=x*10+ch-'0';
                add(i,x+n,inf);
                if(ch=='\n')break;
            }
        }
        for(int i=1;i<=m;i++){
            int w;
            scanf("%d",&w);
            add(i+n,tp,w);
        }
        ll MAX=sum-Dinic(sp,tp);
        memset(vis,false,sizeof(vis));
        dfs(sp);
        for(int i=0;i<exper.size();i++){
            printf("%d%c",exper[i],i==exper.size()-1?'\n':' ');
        }
        for(int i=0;i<tool.size();i++){
            printf("%d%c",tool[i],i==tool.size()-1?'\n':' ');
        }
        printf("%lld\n",MAX);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41955236/article/details/82024924
今日推荐