[FZYZOJ 1355] 8-2 太空飞行计划问题

P1355 -- 8-2 太空飞行计划问题

时间限制:1000MS

内存限制:131072KB

Description

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

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

Input Format

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

Output Format

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

Sample Input

2 3
10 1 2
25 2 3
5 6 7

Sample Output

1 2
1 2 3
17

Hint

【题解+吐槽】
今天IOI day1,恭喜杜教成功AK,rank1,恭喜ChinaTeam总分比USATeam高,3Au1Ag,预祝day2:4AK!
听说T1签到题T2恶心题T3卡时题
听说尼日利亚队集体爆0为了引出大新闻- -
 
回到正事
这题最小割模型。
每个实验像S连边,费用为可得费用,累计进total。
每个仪器像T连边,费用为要花费的费用。
实验要用到的仪器 连边,费用为INF(表示不能割)。
跑最小割就好了
一直以为dinic写错了原来是建图脑洞太大一个地方错了TAT
  1 #include <stdio.h>
  2 #include <queue>
  3 #include <string.h>
  4 #include <iostream>
  5 using namespace std;
  6 const int V=210,E=100010;
  7 int head[V],next[E],to[E],flow[E];
  8 int m,n,S,T,tot=1,total;
  9 bool vis[V];
 10 inline int min(int a,int b) {
 11     return a<b?a:b;
 12 }
 13 inline void add(int u,int v,int fl) {
 14     tot++;
 15     to[tot]=v;
 16     next[tot]=head[u];
 17     head[u]=tot;
 18     flow[tot]=fl;
 19     tot++;
 20     to[tot]=u;
 21     next[tot]=head[v];
 22     head[v]=tot;
 23     flow[tot]=0;
 24 }
 25 
 26 int c[V];
 27 
 28 queue<int> q;
 29 inline void clean() {
 30     while(!q.empty())
 31         q.pop();
 32 }
 33 
 34 inline bool bfs() {
 35     memset(c,0,sizeof(c));
 36     clean();
 37     q.push(S);
 38     c[S]=1;
 39     while(!q.empty()) {
 40         int top=q.front();
 41         q.pop();
 42         for (int i=head[top];i;i=next[i]) {
 43             int _to=to[i],_flow=flow[i];
 44             if(_flow==0 || c[_to]>0) continue;
 45             c[_to]=c[top]+1;
 46             q.push(_to);
 47             if(_to==T) return 1;
 48         }
 49     }
 50     return 0;
 51 }
 52 
 53 int dfs(int now,int low) {
 54     if (now==T) return low;
 55     int flowx,r=low;
 56     for (int i=head[now];i;i=next[i]) {
 57         int _to=to[i],_flow=flow[i];
 58         if(c[_to]!=c[now]+1 || _flow==0) continue;
 59         flowx=dfs(_to,min(r,_flow));
 60         r-=flowx;
 61         flow[i]-=flowx, flow[i^1]+=flowx;
 62         if(!r) return low;
 63     }
 64     if(r==low) c[now]=-1;
 65     return low-r;
 66 }
 67 
 68 inline int dinic() {
 69     int ansx=0;
 70     while(bfs()) ansx+=dfs(S,210000000);
 71     return ansx;
 72 }
 73 
 74 int main() {
 75     scanf("%d%d",&m,&n);
 76     S=0;
 77     T=n+m+1;
 78     for (int i=1,cost;i<=m;++i) {
 79         char str;
 80         scanf("%d%c",&cost,&str);
 81         total+=cost;
 82         add(S,i,cost);
 83         while(str!='\n') {
 84             scanf("%d%c",&cost,&str);
 85             add(i,cost+m,210000000);
 86         }
 87     }
 88     for (int i=1,cost;i<=n;++i) {
 89         scanf("%d",&cost);
 90         add(i+m,T,cost);
 91     }
 92     int answer=total-dinic();
 93     for (int i=head[S];i;i=next[i])
 94         if(flow[i])
 95             printf("%d ",to[i]);
 96     printf("\n");
 97     for (int i=head[T];i;i=next[i]) {
 98         //cout<<i<<' '<<flow[i]<<endl;
 99         if(flow[i]) printf("%d ", to[i]-m);
100     }
101     printf("\n%d\n",answer);
102     return 0;
103 }
View Code

网络流建图一直都那么坑TAT

 
 
posted @ 2015-07-28 22:29  TonyFang  阅读(426)  评论(0编辑  收藏  举报