洛谷 P2762 太空飞行计划问题

题目描述

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行是仪器编号;最后一行是净收益。

 

输入输出样例

输入样例#1: 复制
2 3
10 1 2
25 2 3
5 6 7
输出样例#1: 复制
1 2
1 2 3
17

说明

感谢@zhouyonglong 提供spj

n,m<=50

这道题数据是在windows生成的,输入数据中所有的换行都是'\r\n'而不是'\n'
读入某实验需要用到的仪器编号的时候,可以这么读入。(感谢@zhouyonglong的提供)

char tools[10000];
memset(tools,0,sizeof tools);
cin.getline(tools,10000);
int ulen=0,tool;
while (sscanf(tools+ulen,"%d",&tool)==1)//之前已经用scanf读完了赞助商同意支付该实验的费用
{//tool是该实验所需仪器的其中一个      
    //这一行,你可以将读进来的编号进行储存、处理,如连边。
    if (tool==0) 
        ulen++;
    else {
        while (tool) {
            tool/=10;
            ulen++;
        }
    }
    ulen++;
}

 

思路:输入错误,网络刘高一下就出来了,建图也很简单。

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 10000
using namespace std;
queue<int>que;
int n,m,tot=1,ans,scr,decc,sum;
int to[MAXN],from[MAXN],net[MAXN],cap[MAXN],cur[MAXN],lev[MAXN];
void add(int u,int v,int w){
    to[++tot]=v;net[tot]=from[u];cap[tot]=w;from[u]=tot;
    to[++tot]=u;net[tot]=from[v];cap[tot]=0;from[v]=tot;
}
bool bfs(){
    for(int i=scr;i<=decc;i++){
        lev[i]=-1;
        cur[i]=from[i];
    }
    while(!que.empty())    que.pop();
    que.push(scr);
    lev[scr]=0;
    while(!que.empty()){
        int now=que.front();
        que.pop();
        for(int i=from[now];i!=-1;i=net[i])
            if(lev[to[i]]==-1&&cap[i]>0){
                lev[to[i]]=lev[now]+1;
                que.push(to[i]);
                if(to[i]==decc)    return true;
            }
    }
    return false;
}
int dinic(int now,int flow){
    if(now==decc)    return flow;
    int rest=0,detal;
    for(int & i=cur[now];i!=-1;i=net[i])
        if(lev[to[i]]==lev[now]+1&&cap[i]>0){
            detal=dinic(to[i],min(flow-rest,cap[i]));
            if(detal){
                rest+=detal;
                cap[i]-=detal;
                cap[i^1]+=detal;
                if(rest==flow)    break;
            }
        }
    if(rest!=flow)    lev[now]=-1;
    return rest;
}
int main(){
    memset(from,-1,sizeof(from));
    cin>>m>>n;
    scr=0;decc=m+n+1;
    for(int i=1;i<=m;i++){
        int w;string s;
        cin>>w;sum+=w;
        add(scr,i,w);
        /*getline(cin,s);
        for(int j=0;j<s.length();j++){
            if(s[j]==' ')    continue;
            else{
                int v=s[j]-'0';
                add(i,v+m,0x7fffffff);
            }
        }*/
        while(getchar()!='\n') {  
            int v;scanf("%d",&v);  
            add(i,v+m,0x7fffffff);  
        } 
    }
    for(int i=1;i<=n;i++){
        int w;cin>>w;
        add(i+m,decc,w);
    }
    while(bfs())
        ans+=dinic(scr,0x7fffffff);
    for(int i=1;i<=m;i++)
        if(lev[i]!=-1)    cout<<i<<" ";
    cout<<endl;
    for(int i=1;i<=n;i++)
        if(lev[i+m]!=-1)    cout<<i<<" ";
    cout<<endl;
    cout<<sum-ans;
}

 

posted @ 2018-03-10 07:32  一蓑烟雨任生平  阅读(125)  评论(0编辑  收藏  举报