题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5855

Less Time, More profit

Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
#### 问题描述
> The city planners plan to build N plants in the city which has M shops.
>
> Each shop needs products from some plants to make profit of proi units.
>
> Building ith plant needs investment of payi units and it takes ti days.
>
> Two or more plants can be built simultaneously, so that the time for building multiple plants is maximum of their periods(ti).
>
> You should make a plan to make profit of at least L units in the shortest period.
#### 输入
> First line contains T, a number of test cases.
>
> For each test case, there are three integers N, M, L described above.
>
> And there are N lines and each line contains two integers payi, ti(1
> Last there are M lines and for each line, first integer is proi, and there is an integer k and next k integers are index of plants which can produce material to make profit for the shop.
>
> 1 1 1≤L,ti≤1000000000
> 1≤payi,proi≤30000
#### 输出
> For each test case, first line contains a line “Case #x: t p”, x is the number of the case, t is the shortest period and p is maximum profit in t hours. You should minimize t first and then maximize p.
>
> If this plan is impossible, you should print “Case #x: impossible”
#### 样例
> **sample input**
> 2
>
> 1 1 2
> 1 5
> 3 1 1
>
> 1 1 3
> 1 5
> 3 1 1
>
> **sample output**
> Case #1: 5 2
> Case #2: impossible

题意

有n个工厂,建每个工厂需要花费payi,并且要ti天才能建完。

有m个商店,每个商店能盈利proi,并且需要若干个指定的工厂给它提供原料(缺一不可)。

现在问如何在最短的时间内收益最大。

题解

最大权闭合子图的裸题。(百度文库里面的算法合集之最小割的论文里面有详细介绍最大权闭合子图)

我们二分时间t,然后问题转化成了对满足条件的工厂与商店之间的图求一个最大权闭合子图的问题。我们按照最大权闭合子图的建图方式连边就行了。

建图:

增设源点0,汇点n+m+1。

源点向每个能够满足条件的商店(如果商店的一个需求工厂在时间上不满足条件,那么这个商店就不满足条件,直接忽视它)连边,容量为商店的利润。

商店向需求工厂建边,容量为无穷大。

工厂向汇点建边,容量为工厂的花费。

然后跑最大流,判断在二分的时间下,是否能创造大于等于L的利润。

代码

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
//#define lson (o<<1)
//#define rson ((o<<1)|1)
//#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++) typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=444; struct Edge {
int u,v,cap,flow;
Edge(int u,int v,int c,int f):u(u),v(v),cap(c),flow(f) {}
}; struct Dinic {
int n,m,s,t;
vector<Edge> egs;
vector<int> G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn]; void init(int n) {
this->n=n;
rep(i,0,n+1) G[i].clear();
egs.clear();
m=0;
} void addEdge(int u,int v,int cap) {
egs.pb(Edge(u,v,cap,0));
egs.pb(Edge(v,u,0,0));
m=egs.sz();
G[u].pb(m-2);
G[v].pb(m-1);
} bool BFS() {
clr(vis,0);
queue<int> Q;
Q.push(s);
d[s]=0;
vis[s]=1;
while(!Q.empty()) {
int x=Q.front();
Q.pop();
rep(i,0,G[x].sz()) {
Edge& e=egs[G[x][i]];
if(!vis[e.v]&&e.cap>e.flow) {
vis[e.v]=1;
d[e.v]=d[x]+1;
Q.push(e.v);
}
}
}
return vis[t];
} int DFS(int x,int a) {
if(x==t||a==0) return a;
int flow=0,f;
for(int& i=cur[x]; i<G[x].size(); i++) {
Edge& e=egs[G[x][i]];
if(d[x]+1==d[e.v]&&(f=DFS(e.v,min(a,e.cap-e.flow)))>0) {
e.flow+=f;
egs[G[x][i]^1].flow-=f;
flow+=f;
a-=f;
if(a==0) break;
}
}
return flow;
} int Maxflow(int s,int t) {
this->s=s;
this->t=t;
int flow=0;
while(BFS()) {
clr(cur,0);
flow+=DFS(s,INF);
}
return flow;
}
} dinic; PII plants[maxn];
int pi[maxn],vis[maxn];
vector<int> G[maxn]; int n,m,L; int isok(int mid) {
dinic.init(n+m+2);
clr(vis,0);
for(int i=1; i<=m; i++) {
rep(j,0,G[i].size()) {
int v=G[i][j];
if(plants[v].Y>mid) {
vis[i]=1;
break;
}
}
}
int sumv=0;
for(int i=1; i<=m; i++) {
if(vis[i]) continue;
sumv+=pi[i];
dinic.addEdge(0,i,pi[i]);
rep(j,0,G[i].size()) {
int v=G[i][j];
dinic.addEdge(i,v+m,INF);
}
}
rep(i,1,n+1) {
if(plants[i].Y>mid) continue;
dinic.addEdge(i+m,m+n+1,plants[i].X);
}
return sumv-dinic.Maxflow(0,n+m+1);
} void init() {
rep(i,0,maxn) G[i].clear();
} int main() {
int tc,kase=0;
scanf("%d",&tc);
while(tc--) {
scanf("%d%d%d",&n,&m,&L);
init();
rep(i,1,n+1) {
scanf("%d%d",&plants[i].X,&plants[i].Y);
}
rep(i,1,m+1) {
scanf("%d",&pi[i]);
int cnt;
scanf("%d",&cnt);
while(cnt--) {
int x;
scanf("%d",&x);
G[i].push_back(x);
}
}
printf("Case #%d: ",++kase);
int l=0,r=1000000000;
if(isok(r)<L) {
puts("impossible");
continue;
}
while(l+1<r) {
int mid=l+(r-l)/2;
if(isok(mid)>=L) r=mid;
else l=mid;
}
printf("%d %d\n",r,isok(r));
}
return 0;
} //end-----------------------------------------------------------------------
/*
5 3 50
1 1
2 2
3 3
4 4
5 5
100 2 1 4
1 0
1 0
*/

HDU 5855 Less Time, More profit 最大权闭合子图的更多相关文章

  1. Less Time, More profit 最大权闭合子图(最大流最小割)

    The city planners plan to build N plants in the city which has M shops. Each shop needs products fro ...

  2. HDU5855 Less Time, More profit(最大权闭合子图)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5855 Description The city planners plan to build ...

  3. hdu 5772 String problem 最大权闭合子图

    String problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5772 Description This is a simple pro ...

  4. HDU 3879 Base Station(最大权闭合子图)

    经典例题,好像说可以转化成maxflow(n,n+m),暂时只可以勉强理解maxflow(n+m,n+m)的做法. 题意:输入n个点,m条边的无向图.点权为负,边权为正,点权为代价,边权为获益,输出最 ...

  5. hdu 3917 Road constructions 最大权闭合子图

    样例说明: n(城市数目)   m(工程队数目) 每个工程队上交的税收 val[i] k(k个工程) xi   yi  ci  costi , 工程队ci承包由xi到yi,政府的补贴为costi 注意 ...

  6. 2018.11.06 NOIP训练 最大获利(profit)(01分数规划+最大权闭合子图)

    传送门 好题啊. ∑i<jpi,jK∗(200−K)>X\frac{\sum_{i<j}p_{i,j}}{K*(200-K)}>XK∗(200−K)∑i<j​pi,j​​ ...

  7. HDU 3879 Base Station(最大权闭合子图)

    将第i个用户和他需要的基站连边,转化成求二分图的最大权闭合子图. 答案=正权点之和-最小割. # include <cstdio> # include <cstring> # ...

  8. HDU4971 A simple brute force problem.(强连通分量缩点 + 最大权闭合子图)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4971 Description There's a company with several ...

  9. 【POJ 2987】Firing (最小割-最大权闭合子图)

    裁员 [问题描述] 在一个公司里,老板发现,手下的员工很多都不务正业,真正干事员工的没几个,于是老板决定大裁员,每开除一个人,同时要将其下属一并开除,如果该下属还有下属,照斩不误.给出每个人的贡献值和 ...

随机推荐

  1. 修复 Cydia 不能上网的问题

    使用 h3lix 越狱 10.3.3 的 iPhone5,进入 Cydia 不能联网解决方法:打开 Cydia,进入已安装列表,点击 Cydia Installer 卸载,然后看到桌面上就没有 Cyd ...

  2. 课时17.WebStorm安装(理解)

    开发工具(工欲善其事,必先利其器) 为了让大家更快的融入到编程的世界中去,不被繁琐的英文单词所困扰,不用每天编写很多没有意义的重复代码,提升大家的开发效率,今后的课程中我们统一采用开发工具来编写网页 ...

  3. 2017-2018-1 20155318《信息安全技术》实验二——Windows口令破解

    2017-2018-1 20155318<信息安全技术>实验二--Windows口令破解 一.实验原理 口令破解方法 口令破解主要有两种方法:字典破解和暴力破解. 字典破解是指通过破解者对 ...

  4. WPF GDI+字符串绘制成图片(二)

    原文:WPF GDI+字符串绘制成图片(二) 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/BYH371256/article/details/83 ...

  5. WPF MVVM从入门到精通8:数据验证

    原文:WPF MVVM从入门到精通8:数据验证 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通3:数据绑定 WPF M ...

  6. [BZOJ4002][JLOI2015]有意义的字符串-[快速乘法+矩阵乘法]

    Description 传送门 Solution 由于这里带了小数,直接计算显然会爆掉,我们要想办法去掉小数. 而由于原题给了暗示:b2<=d<=(b+1)2,我们猜测可以利用$(\fra ...

  7. OpenCV中Mat操作clone() 与copyto()的区别

    OpenCV中Mat操作clone() 与copyto()的区别 // Mat is basically a class with two data parts: the matrix header ...

  8. 【LG3237】[HNOI2014]米特运输

    题面 洛谷 题解 代码 #include <iostream> #include <cstdio> #include <cstdlib> #include < ...

  9. MySQL入门篇(二)之常见命令管理

    一.SQL结构化查询语言 SQL,英文全称Structured Query Language,中文意思是结构化查询语言.它是一种对关系数据库中的数据进行定义和操作的语言方法,是大多数关系数据库管理系统 ...

  10. iOS 中架构模式的浅显理解

    我们开发软件中应用各种模式,主要是为了 职责划分:一个类只做一件事 易用,可维护,方便扩展 解耦,相互独立,可单独测试 各种设计模式其实都是在解决上面的问题,让我们对比看看吧. 一.如何理解MVC设计 ...