HDU5855 Less Time, More profit(最大权闭合子图)
题目
Source
http://acm.hdu.edu.cn/showproblem.php?pid=5855
Description
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.
Input
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<= i <= N).
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 <= T <= 30
1 <= N, M <= 200
1≤L,ti≤1000000000
1≤payi,proi≤30000
Output
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个商店,如果各个商店所需要k间工厂都建了,那么就得到proi的收益。现在希望收益大于等于l,问在建工厂所花时间最少的前提下,能获得的最大收益是多少。
二分时间,判定最大收益能否大于等于l;而求最大收益,这就是典型的最大权闭合子图的模型了,最小割求解即可。
代码
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 444
#define MAXM 444*888 struct Edge{
int v,cap,flow,next;
}edge[MAXM];
int vs,vt,NE,NV;
int head[MAXN]; void addEdge(int u,int v,int cap){
edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0;
edge[NE].next=head[v]; head[v]=NE++;
} int level[MAXN];
int gap[MAXN];
void bfs(){
memset(level,-1,sizeof(level));
memset(gap,0,sizeof(gap));
level[vt]=0;
gap[level[vt]]++;
queue<int> que;
que.push(vt);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(level[v]!=-1) continue;
level[v]=level[u]+1;
gap[level[v]]++;
que.push(v);
}
}
} int pre[MAXN];
int cur[MAXN];
int ISAP(){
bfs();
memset(pre,-1,sizeof(pre));
memcpy(cur,head,sizeof(head));
int u=pre[vs]=vs,flow=0,aug=INF;
gap[0]=NV;
while(level[vs]<NV){
bool flag=false;
for(int &i=cur[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){
flag=true;
pre[v]=u;
u=v;
//aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
aug=min(aug,edge[i].cap-edge[i].flow);
if(v==vt){
flow+=aug;
for(u=pre[v]; v!=vs; v=u,u=pre[u]){
edge[cur[u]].flow+=aug;
edge[cur[u]^1].flow-=aug;
}
//aug=-1;
aug=INF;
}
break;
}
}
if(flag) continue;
int minlevel=NV;
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==0) break;
level[u]=minlevel+1;
gap[level[u]]++;
u=pre[u];
}
return flow;
} int n,m,l;
int pay[222],time[222],pro[222];
vector<int> need[222]; int isok(int t){
vs=0; vt=n+m+1; NV=vt+1; NE=0;
memset(head,-1,sizeof(head));
int totpro=0;
for(int i=1; i<=n; ++i){
if(time[i]<=t) addEdge(i+m,vt,pay[i]);
}
for(int i=1; i<=m; ++i){
bool flag=1;
for(int j=0; j<need[i].size(); ++j){
if(time[need[i][j]]>t){
flag=0;
break;
}
}
if(flag==0) continue;
addEdge(vs,i,pro[i]);
totpro+=pro[i];
for(int j=0; j<need[i].size(); ++j){
addEdge(i,need[i][j]+m,INF);
}
}
int res=totpro-ISAP();
if(res>=l) return res;
return -1;
} int main(){
int t;
scanf("%d",&t);
for(int cse=1; cse<=t; ++cse){
scanf("%d%d%d",&n,&m,&l);
for(int i=1; i<=n; ++i){
scanf("%d%d",&pay[i],&time[i]);
}
for(int i=1; i<=m; ++i) need[i].clear();
for(int i=1; i<=m; ++i){
int a,b;
scanf("%d%d",&pro[i],&a);
for(int j=0; j<a; ++j){
scanf("%d",&b);
need[i].push_back(b);
}
}
int l=0,r=1000000001;
while(l<r){
int mid=l+r>>1;
if(isok(mid)!=-1) r=mid;
else l=mid+1;
}
printf("Case #%d: ",cse);
if(l==1000000001){
puts("impossible");
continue;
}
printf("%d %d\n",l,isok(l));
}
return 0;
}
HDU5855 Less Time, More profit(最大权闭合子图)的更多相关文章
- HDU 5855 Less Time, More profit 最大权闭合子图
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5855 Less Time, More profit Time Limit: 2000/1000 MS ...
- Less Time, More profit 最大权闭合子图(最大流最小割)
The city planners plan to build N plants in the city which has M shops. Each shop needs products fro ...
- 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<jpi,j ...
- HDU4971 A simple brute force problem.(强连通分量缩点 + 最大权闭合子图)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4971 Description There's a company with several ...
- 【POJ 2987】Firing (最小割-最大权闭合子图)
裁员 [问题描述] 在一个公司里,老板发现,手下的员工很多都不务正业,真正干事员工的没几个,于是老板决定大裁员,每开除一个人,同时要将其下属一并开除,如果该下属还有下属,照斩不误.给出每个人的贡献值和 ...
- 2018.06.27Firing(最大权闭合子图)
Firing Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 11558 Accepted: 3494 Description ...
- POJ 2987 - Firing - [最大权闭合子图]
题目链接:http://poj.org/problem?id=2987 Time Limit: 5000MS Memory Limit: 131072K Description You’ve fina ...
- BZOJ1565 [NOI2009]植物大战僵尸(拓扑排序 + 最大权闭合子图)
题目 Source http://www.lydsy.com/JudgeOnline/problem.php?id=1565 Description Input Output 仅包含一个整数,表示可以 ...
- HDU 3879 Base Station(最大权闭合子图)
经典例题,好像说可以转化成maxflow(n,n+m),暂时只可以勉强理解maxflow(n+m,n+m)的做法. 题意:输入n个点,m条边的无向图.点权为负,边权为正,点权为代价,边权为获益,输出最 ...
随机推荐
- September 9th 2016 Week 37th Friday
Within you, I lose myself. 有了你,我迷失了自我. I never had such feeling, maybe just because I never invested ...
- August 7th 2016, Week 33rd Sunday
Knowing yourself is the height of wisdom. 了解自己就是大智慧. Two-day holiday, even I didn't have enought tim ...
- ssh-keygen详解
先来一段google wiki关于ssh key的解释,对应的连接为:https://wiki.archlinux.org/index.php/SSH_keys_(%E7%AE%80%E4%BD%93 ...
- TCP/IP的Socket编程
1. TCP/IP.UDP的基本概念 TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,他是一个工业标准的协议集, ...
- php单双引号
1.定义字符串 定义字符串时,只有一种引号被视为定义符,即单引号或双引号.于是,如果一个字符串由双引号开始,那么只有双引号被分析器解析.这样,你就可以在双引号串中包含任何其他字符,甚至单引号.下面的引 ...
- 聊聊SOA面向服务架构
什么是SOA SOA(Service-Oriented Architecture),即面向服务的架构.SOA是一种粗粒度.松耦合服务架构,服务之间通过简单.精确定义接口进行通讯,不涉及底层编程接口和通 ...
- 【转载】Pyqt 添加右键菜单方法
转载地址: http://www.cnblogs.com/yogalau/p/3954042.html?utm_source=tuicool QListWidget 是继承 QWidget 的, 所以 ...
- nodejs2
jade@1.11.0 严格注意缩进 extends layout block content h1= title p Welcome to #{title} - var a='abc'; p his ...
- css 妙味 总结
技巧一: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...
- php判断访问的当前设备是手机还是电脑
<?php function isMobile(){ $useragent=isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AG ...