博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LuoguP2762 太空飞行计划问题(最大权闭合子图,最小割)
阅读量:4625 次
发布时间:2019-06-09

本文共 2899 字,大约阅读时间需要 9 分钟。

题目描述

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 #include
2 #include
3 #include
4 #include
5 #include
6 const int oo=0x3f3f3f3f; 7 struct pnt{ 8 int hd; 9 int lyr; 10 int now; 11 }p[10001]; 12 struct ent{ 13 int twd; 14 int lst; 15 int vls; 16 }e[1000000]; 17 int cnt; 18 int n,m; 19 int s,t; 20 int sum; 21 char tmp[100000]; 22 std::queue
Q; 23 void ade(int f,int t,int v) 24 { 25 cnt++; 26 e[cnt].twd=t; 27 e[cnt].vls=v; 28 e[cnt].lst=p[f].hd; 29 p[f].hd=cnt; 30 return ; 31 } 32 bool Bfs(void) 33 { 34 while(!Q.empty()) 35 Q.pop(); 36 for(int i=1;i<=t;i++) 37 p[i].lyr=0; 38 p[s].lyr=1; 39 Q.push(s); 40 while(!Q.empty()) 41 { 42 int x=Q.front(); 43 Q.pop(); 44 for(int i=p[x].hd;i;i=e[i].lst) 45 { 46 int to=e[i].twd; 47 if(p[to].lyr==0&&e[i].vls>0) 48 { 49 p[to].lyr=p[x].lyr+1; 50 if(to==t) 51 return true; 52 Q.push(to); 53 } 54 } 55 } 56 return false; 57 } 58 int Dfs(int x,int fll) 59 { 60 if(x==t) 61 return fll; 62 for(int& i=p[x].now;i;i=e[i].lst) 63 { 64 int to=e[i].twd; 65 if(p[to].lyr==p[x].lyr+1&&e[i].vls>0) 66 { 67 int ans=Dfs(to,std::min(fll,e[i].vls)); 68 if(ans>0) 69 { 70 e[i].vls-=ans; 71 e[((i-1)^1)+1].vls+=ans; 72 return ans; 73 } 74 } 75 } 76 return 0; 77 } 78 int Dinic(void) 79 { 80 int ans=0; 81 while(Bfs()) 82 { 83 int dlt; 84 for(int i=1;i<=t;i++) 85 p[i].now=p[i].hd; 86 while(dlt=Dfs(s,oo)) 87 ans+=dlt; 88 } 89 return ans; 90 } 91 int main() 92 { 93 // freopen("a.in","r",stdin); 94 scanf("%d%d",&m,&n); 95 s=n+m+1; 96 t=s+1; 97 for(int i=1;i<=m;i++) 98 { 99 int v;100 scanf("%d",&v);101 sum+=v;102 ade(s,i,v);103 ade(i,s,0);104 int len=0;105 memset(tmp,0,sizeof(tmp));106 std::cin.getline(tmp,10000);107 while(sscanf(tmp+len,"%d",&v)==1)108 {109 ade(i,v+m,oo);110 ade(v+m,i,0);111 if(v==0)len++;112 else{113 while(v)114 {115 len++;116 v/=10;117 }118 }119 len++;120 }121 }122 for(int i=1;i<=n;i++)123 {124 int v;125 scanf("%d",&v);126 ade(i+m,t,v);127 ade(t,i+m,0);128 }129 int ans=Dinic();130 for(int i=1;i<=m;i++)131 {132 if(p[i].lyr>1)133 printf("%d ",i);134 }135 puts("");136 for(int i=1;i<=n;i++)137 {138 if(p[i+m].lyr>1)139 printf("%d ",i);140 }141 puts("");142 printf("%d\n",sum-ans);143 return 0;144 }

 

转载于:https://www.cnblogs.com/blog-Dr-J/p/10205541.html

你可能感兴趣的文章
ArcPy开发教程2-管理地图文档1
查看>>
过滤器的使用
查看>>
软件测试
查看>>
Js 提交 form 表单
查看>>
Response.Status http协议状态代码
查看>>
BZOJ4925 城市规划
查看>>
Bootstrap 辅助类
查看>>
[]和{},类的简写
查看>>
二分算法(折半算法)详解
查看>>
掌握 需求过程阅读笔记04
查看>>
JS判断手机浏览器
查看>>
@Autowired和@Resource的区别
查看>>
TCP、UDP、HTTP、SOCKET之间的区别
查看>>
根据Buffer中的图片数据进行图片呈现的方法.
查看>>
用Python编写WordCount程序任务
查看>>
AC日记——传纸条 洛谷 P1006
查看>>
Android Gradle 多Module单独编译一个Module
查看>>
React显示文件夹中SVG
查看>>
编码规范小结
查看>>
695. Max Area of Island
查看>>