HDU - 5855 Less Time, More profit 最大权闭合子图 + 二分
传送门:HDU 5855
题意:
有n个工厂,m个商店
每个工厂有建造时间ti,花费payi
每个商店和k个工厂有关,如果这k个工厂都建造了,那么能获利proi
问你求收益(∑pro−∑pay)≥L时,首先满足时间t最小,其次是收益p最大
显然要满足最长的时间最短要二分,我们将商店向工厂连边,由于商店需要的所有工厂都要建设才能使商店获利,因此显然最后选择出来的
商店和工厂的点集是一个闭合子图,那么题目自然就是求最大权闭合子图啦,剩下的就是老套路了。
第一次自己做出来比赛题中的网络流,虽说是个签到题吧,但是还是美滋滋啊。
代码:
//ISAP int
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define ll long long
#define MAXN 10005
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int, int> P;
int n;//实际建图点数(最好比图中总点数大一点)
struct Edge{int v,next;int cap,flow;
}edge[MAXN*100];
int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN];
int cnt=0;//实际存储总边数
void init()
{cnt=0;memset(pre,-1,sizeof(pre));
}
void add(int u,int v,int w,int rw=0)//加边 有向图三个参数,无向图四个
{edge[cnt].v=v;edge[cnt].cap=w;edge[cnt].flow=0;edge[cnt].next=pre[u];pre[u]=cnt++;edge[cnt].v=u;edge[cnt].cap=rw;edge[cnt].flow=0;edge[cnt].next=pre[v];pre[v]=cnt++;
}
bool bfs(int s,int t)//其实这个bfs可以融合到下面的迭代里,但是好像是时间要长
{memset(dep,-1,sizeof(dep));memset(gap,0,sizeof(gap));gap[0]=1;dep[t]=0;queue<int>q;while(!q.empty())q.pop();q.push(t);//从汇点开始反向建层次图 while(!q.empty()){int u=q.front();q.pop();for(int i=pre[u];i!=-1;i=edge[i].next){int v=edge[i].v;if(dep[v]==-1&&edge[i^1].cap>edge[i^1].flow)//注意是从汇点反向bfs,但应该判断正向弧的余量{dep[v]=dep[u]+1;gap[dep[v]]++;q.push(v);//if(v==s)//感觉这两句优化加了一般没错,但是有的题可能会错,所以还是注释出来,到时候视情况而定 //break;} }}return dep[s]!=-1;
}
int isap(int s,int t)
{bfs(s,t);memcpy(cur,pre,sizeof(pre));int u=s;path[u]=-1;int ans=0;while(dep[s]<n)//迭代寻找增广路 {if(u==t){int f=inf;for(int i=path[u];i!=-1;i=path[edge[i^1].v])//修改找到的增广路 f=min(f,edge[i].cap-edge[i].flow);for(int i=path[u];i!=-1;i=path[edge[i^1].v]){edge[i].flow+=f;edge[i^1].flow-=f;}ans+=f;u=s;continue;}bool flag=false;int v;for(int i=cur[u];i!=-1;i=edge[i].next){v=edge[i].v;if(dep[v]+1==dep[u]&&edge[i].cap-edge[i].flow){cur[u]=path[v]=i;//当前弧优化 flag=true;break;}}if(flag){u=v;continue;}int x=n;if(!(--gap[dep[u]]))return ans;//gap优化 for(int i=pre[u];i!=-1;i=edge[i].next){if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x){x=dep[edge[i].v];cur[u]=i;//常数优化 }}dep[u]=x+1;gap[dep[u]]++;if(u!=s)//当前点没有增广路则后退一个点 u=edge[path[u]^1].v;} return ans;
}
struct plant{int pay, t;
}p[220];
int val[220];
int N, M, L, source, sink;
vector<int> shop[220];
int build(int up)
{bool flag = 0;int sum = 0;for(int i = 1; i <= M; i++){flag = 0;for(int j = 0; j < shop[i].size(); j++){if(p[shop[i][j]].t > up) flag = 1;}if(flag) continue;add(source, i, val[i]);sum += val[i];for(int j = 0; j < shop[i].size(); j++){add(i, M + shop[i][j], inf);}}for(int i = 1; i <= N; i++){add(i + M, sink, p[i].pay);}return sum;
}
P solve(int up)
{source = 0, sink = N + M + 1;n = sink + 1;int l = 0, r = up + 1, mid, sum, tmp, max_flow;while(l <= r){mid = (l + r) >> 1;init();sum = build(mid);tmp = isap(source, sink);if(sum - tmp >= L)r = mid - 1, max_flow = sum - tmp;elsel = mid + 1;}return P(r + 1, max_flow);
}
int main()
{int T, kase = 1;int k, u, v;cin >> T;while(T--){int up = 0;scanf("%d %d %d", &N, &M, &L);for(int i = 0; i <= M; i++) shop[i].clear();for(int i = 1; i <= N; i++){scanf("%d %d", &p[i].pay, &p[i].t);up = max(up, p[i].t);}for(int i = 1; i <= M; i++){scanf("%d", val + i);scanf("%d", &k);while(k--){scanf("%d", &u);shop[i].push_back(u);}}P ans = solve(up);if(ans.first > up) printf("Case #%d: impossible\n", kase++);else printf("Case #%d: %d %d\n", kase++, ans.first, ans.second);}
}
HDU - 5855 Less Time, More profit 最大权闭合子图 + 二分相关推荐
- hdu 3917 Road constructions 最大权闭合子图
样例说明: n(城市数目) m(工程队数目) 每个工程队上交的税收 val[i] k(k个工程) xi yi ci costi , 工程队ci承包由xi到yi,政府的补贴为costi 注意 ...
- 最大权闭合子图(poj 2987 Firing)
Firing Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 10884 Accepted: 3286 Descript ...
- 2018.06.27Firing(最大权闭合子图)
Firing Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 11558 Accepted: 3494 Description ...
- poj 2987 Firing (最大权闭合子图)
Firing Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 10248 Accepted: 3110 Descript ...
- 最大权闭合子图(RMRC2017 Open-Pit Mining)
闭合图:对于一个有向图G,存在点集合V,任取点u属于V,u的出边的另一个点也属于V,则为闭合图. 理解:任取一起点,终点必定是无出度的点. 最大权闭合子图:当每个点有一个权值w(有正有负),点权和最大 ...
- poj 2987 Firing【最大权闭合子图+玄学计数 || BFS】
玄学计数 LYY Orz 第一次见这种神奇的计数方式,乍一看非常不靠谱但是仔细想想还卡不掉 就是把在建图的时候把正权变成w*10000-1,负权变成w*10000+1,跑最大权闭合子图.后面的1作用是 ...
- 最大权闭合子图(最小割)
最大权闭合子图(最大流最小割) •参考资料 [1]最大权闭合子图 •权闭合子图 存在一个图的子图,使得子图中的所有点出度指向的点依旧在这个子图内,则此子图是闭合子图. 在这个图中有8个闭合子图:∅,{ ...
- 【转载】最大权闭合子图 【网络流】
原文链接 定义 所谓闭合子图就是给定一个有向图,从中选择一些点组成一个点集V.对于V中任意一个点,其后续节点都仍然在V中. 建模 首先建立源点s和汇点t,将源点s与所有权值为正的点相连,容量为权值:将 ...
- Cogs 727. [网络流24题] 太空飞行计划(最大权闭合子图)
[网络流24题] 太空飞行计划 ★★☆ 输入文件:shuttle.in 输出文件:shuttle.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] W 教授正在为国家航天中心计 ...
- #1398 : 网络流五·最大权闭合子图
题目链接 结论 最大权闭合子图的权值 === 所有正权点之和−-−最小割 简单割(或最小割)将有向图分成两类,与源点sss相连的称为SSS,与汇点ttt相连的称为TTT 割的流量===与sss相连的正 ...
最新文章
- MobileNet Unet
- 设计模式:单例模式之懒汉式
- python安装pymssql
- Ansible-list-Dictionary-数据格式
- java如何爬取304_HTTP 304错误的详细讲解
- spring boot+mybatis整合
- java第一次上机_java第一次上机实验--验证码
- Python自动化开发学习的第九周----线程、进程、协程
- colordialog通过哪属性取其颜色_IT兄弟连 HTML5教程 CSS3揭秘 CSS常见的样式属性和值1...
- Linux Tun/Tap网口(/dev/net/tun)的读写方法
- 判断数据类型的几种办法
- 对于集成SP3后后不能激活的解释
- 使用JavaParser进行java源码解析
- ANSYS网格转化为模型、ANSYS网格导入到workbench分析
- c语言人机大战五子棋,五子棋人机大战将打响 祁观将与AI弈心五番棋对决
- 代理的原理及类型总结
- 對Googgle adsense廣告作弊和Googeladsense點擊廣告的生存前景看法
- 微软所有正版软件下载网站ITELLYOU
- 网易云音乐修改名字怎么老是服务器错误,网易云音乐为什么改了名字?网抑云是怎么回事...
- 暗影精灵电脑 开机速度慢的解决方法