2016 Multi-University Training Contest 9
solved 1/13
2016 Multi-University Training Contest 9
二分+最大权闭合图 Less Time, More profit(BH)
题意就是有n个工厂,m个商店
每个工厂有建造时间ti,花费payi
每个商店和k个工厂有关,如果这k个工厂都建造了,那么能获利proi
问你求收益(∑pro−∑pay)≥L时,首先满足时间t最小,其次是收益p最大首先二分时间的答案,然后看那些工厂能建造,然后工厂是花费,商店是收益,并且要与商店有关的工厂都建造了,才能获利,所以这是一个最大权闭合图的问题。
关于最大权闭合图:岐哥的博客
闭合图就是闭合图中的点的后继也在这个闭合图中。而闭合图是反映事物间必要条件的关系的,也就是说一个点是它后继的必要条件。也就是说要有这个点,它的后继点也要都存在。
最大权闭合图:
建图:构造一个源点S,汇点T。我们将S与所有权值为正的点连一条容量为其权值的边,将所有权值为负的点与T连一条容量为其权值的绝对值的边,原来的边将其容量定为正无穷。
求解:最大权闭合图=正的点权和-最小割=正的点权和-最大流。
时间复杂度为.
代码:
#include <bits/stdc++.h> const int N = 200 + 5;
const int INF = 0x3f3f3f3f;
int pay[N], t[N];
int pro[N];
std::vector<int> need[N];
int n, m;
int L; /*
*最大流之Dinic算法:不停地构造层次图,然后用阻塞流增广。
*时间复杂度为 O(n^2*m)。
*如果容量为1,复杂度为 O(min(n^(2/3), m^(1/2)*m)。
*对于二分图最大匹配这样的特殊图,复杂度为 O(n^(1/2)*m)
*/
struct Max_Flow {
struct Edge {
int from, to, cap, flow;
};
std::vector<Edge> edges;
std::vector<int> G[2*N]; //保存每个结点的弧在edges里的序号
int level[2*N], cur[2*N]; //结点在层次图中的等级。结点当前弧下标。
int n, m, s, t;
//初始化顶点个数n,边的个数m在加边时统计,s和t分别为源点和汇点
void init(int n) {
this->n = n;
for (int i=0; i<=n; ++i) {
G[i].clear ();
}
edges.clear ();
}
void add_edge(int from, int to, int cap) {
edges.push_back ((Edge) {from, to, cap, 0});
edges.push_back ((Edge) {to, from, 0, 0});
m = edges.size ();
G[from].push_back (m - 2);
G[to].push_back (m - 1);
}
bool BFS() {
std::fill (level, level+1+n, -1);
std::queue<int> que;
level[s] = 0; que.push (s);
while (!que.empty ()) {
int u = que.front (); que.pop ();
for (int i=0; i<G[u].size (); ++i) {
Edge &e = edges[G[u][i]];
if (level[e.to] == -1 && e.cap > e.flow) {
level[e.to] = level[u] + 1;
que.push (e.to);
}
}
}
return level[t] != -1;
}
int DFS(int u, int a) {
if (u == t || a == 0) {
return a; //a表示当前为止所有弧的最小残量
}
int flow = 0, f;
for (int &i=cur[u]; i<G[u].size (); ++i) {
Edge &e = edges[G[u][i]];
if (level[u] + 1 == level[e.to]
&& (f = DFS (e.to, std::min (a, e.cap - e.flow))) > 0) {
e.flow += f;
edges[G[u][i]^1].flow -= f;
flow += f; a -= f;
if (a == 0) {
break;
}
}
}
return flow;
}
int Dinic(int s, int t) {
this->s = s; this->t = t;
int flow = 0;
while (BFS ()) {
std::fill (cur, cur+1+n, 0);
flow += DFS (s, INF);
}
return flow;
}
}max_flow; int check(int max_t) {
int S = 0, T = n + m + 1;
int sum = 0;
max_flow.init (n+m+2);
for (int i=1; i<=m; ++i) {
max_flow.add_edge (S, i, pro[i]);
bool flag = true;
for (int j: need[i]) {
if (t[j] > max_t) {
flag = false;
break;
}
}
if (flag) {
for (int j: need[i]) {
max_flow.add_edge (i, m+j, INF);
}
sum += pro[i];
}
}
for (int i=1; i<=n; ++i) {
if (t[i] <= max_t)
max_flow.add_edge (m+i, T, pay[i]); //abs (-pay[i])
}
int min_cut = max_flow.Dinic (S, T);
if (sum - min_cut >= L)
return sum - min_cut;
else
return -1;
} void solve(int cas) {
printf ("Case #%d: ", cas);
int best_t = INF, best_p = 0;
int l = 1, r = 1000000000;
while (l <= r) {
int mid = l + r >> 1;
int res = check (mid);
if (res != -1) {
best_t = std::min (best_t, mid);
best_p = res;
r = mid - 1;
} else
l = mid + 1;
}
if (best_t < INF)
printf ("%d %d\n", best_t, best_p);
else
puts ("impossible");
} int main() {
int T;
scanf ("%d", &T);
for (int cas=1; cas<=T; ++cas) {
scanf ("%d%d%d", &n, &m, &L);
for (int i=1; i<=n; ++i) {
scanf ("%d%d", pay+i, t+i);
}
for (int i=1; i<=m; ++i) {
scanf ("%d", pro+i);
need[i].clear ();
int k;
scanf ("%d", &k);
while (k--) {
int id;
scanf ("%d", &id);
need[i].push_back (id);
}
}
solve (cas);
}
return 0;
}
还有贪心的做法,时间复杂度,解释。
代码:
#include <bits/stdc++.h> const int N = 200 + 5;
const int INF = 0x3f3f3f3f; struct Plant {
int pay, t;
}p[N];
std::vector<int> id[N]; struct Shop {
int pro;
std::vector<int> need;
int pay;
int max_t;
int done;
}s[N]; int n, m;
int L; bool vis_p[N], vis_s[N]; int check(int max_t) {
memset (vis_p, false, sizeof (vis_p));
memset (vis_s, false, sizeof (vis_s));
for (int i=0; i<m; ++i)
s[i].done = 0;
int ret = -INF, tmp = 0;
for (; ;) {
int max_val = -INF, k = -1;
for (int i=0; i<m; ++i) {
if (!vis_s[i] && s[i].max_t <= max_t) {
if (max_val < s[i].pro - s[i].pay + s[i].done) {
max_val = s[i].pro - s[i].pay + s[i].done;
k = i;
}
}
}
if (max_val == -INF)
break;
vis_s[k] = true; //max m times
tmp += max_val;
ret = std::max (ret, tmp);
for (int j: s[k].need) {
if (!vis_p[j]) {
vis_p[j] = true;
for (int l: id[j]) {
if (!vis_s[l]) {
s[l].done += p[j].pay;
}
}
}
}
}
return ret >= L ? ret : -1;
} void solve(int cas) {
printf ("Case #%d: ", cas);
int best_t = INF, best_p = 0;
int l = 1, r = 1000000000;
while (l <= r) {
int mid = l + r >> 1;
int res = check (mid);
if (res != -1) {
best_t = std::min (best_t, mid);
best_p = res;
r = mid - 1;
} else
l = mid + 1;
}
if (best_t < INF)
printf ("%d %d\n", best_t, best_p);
else
puts ("impossible");
} int main() {
int T;
scanf ("%d", &T);
for (int cas=1; cas<=T; ++cas) {
scanf ("%d%d%d", &n, &m, &L);
for (int i=0; i<n; ++i) {
scanf ("%d%d", &p[i].pay, &p[i].t);
id[i].clear ();
}
for (int i=0; i<m; ++i) {
scanf ("%d", &s[i].pro);
s[i].need.clear ();
s[i].max_t = -1;
s[i].pay = 0;
int k;
scanf ("%d", &k);
while (k--) {
int j;
scanf ("%d", &j);
j--;
if (p[j].t > s[i].max_t)
s[i].max_t = p[j].t;
s[i].pay += p[j].pay;
s[i].need.push_back (j);
id[j].push_back (i);
}
}
solve (cas);
}
return 0;
}
2016 Multi-University Training Contest 9的更多相关文章
- 2016 Al-Baath University Training Camp Contest-1
2016 Al-Baath University Training Camp Contest-1 A题:http://codeforces.com/gym/101028/problem/A 题意:比赛 ...
- 2016 Al-Baath University Training Camp Contest-1 E
Description ACM-SCPC-2017 is approaching every university is trying to do its best in order to be th ...
- 2016 Al-Baath University Training Camp Contest-1 A
Description Tourist likes competitive programming and he has his own Codeforces account. He particip ...
- 2016 Al-Baath University Training Camp Contest-1 J
Description X is fighting beasts in the forest, in order to have a better chance to survive he's gon ...
- 2016 Al-Baath University Training Camp Contest-1 I
Description It is raining again! Youssef really forgot that there is a chance of rain in March, so h ...
- 2016 Al-Baath University Training Camp Contest-1 H
Description You've possibly heard about 'The Endless River'. However, if not, we are introducing it ...
- 2016 Al-Baath University Training Camp Contest-1 G
Description The forces of evil are about to disappear since our hero is now on top on the tower of e ...
- 2016 Al-Baath University Training Camp Contest-1 F
Description Zaid has two words, a of length between 4 and 1000 and b of length 4 exactly. The word a ...
- 2016 Al-Baath University Training Camp Contest-1 D
Description X is well known artist, no one knows the secrete behind the beautiful paintings of X exc ...
- 2016 Al-Baath University Training Camp Contest-1 C
Description Rami went back from school and he had an easy homework about bitwise operations (and,or, ...
随机推荐
- Lua中的常用函数库汇总
lua库函数 这些函数都是Lua编程语言的一部分, 点击这里了解更多. assert(value) - 检查一个值是否为非nil, 若不是则(如果在wow.exe打开调试命令)显示对话框以及输出错误调 ...
- loadrunner---<三>---菜鸟对Browser Emulation的思考
之前在一个web是项目做性能测试,发现controller中场景运行的时候,mrdv.exe内存所耗内存在不断增加,最后报错停止了 not enough memory for new buffer i ...
- Mysql性能监控
show processlist; show global variables like 'max_allowed_packet'; // QPS计算(每秒查询数)show global status ...
- Autolayout及VFL经验分享
http://www.cocoachina.com/industry/20131108/7322.html 这篇不是什么教程.Cocoa autolayout出来蛮久了.以前多次想去深入研究一下,每次 ...
- POJ 2492 并查集扩展(判断同性恋问题)
G - A Bug's Life Time Limit:10000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u S ...
- 【Django】Django 如何实现 如下 联表 JOIN 查询?
SQL语句: select distinct a.device_hash, sum(b.cmn_merge_count) from (select distinct device_hash from ...
- 【leetcode】Best Time to Buy and Sell Stock III
Best Time to Buy and Sell Stock III Say you have an array for which the ith element is the price of ...
- 对于sharepoint 的解决方案的实际说明
对于sharepoint 的解决方案 实际上就是cab的包 你把***.wsp改为***.cab我们就可以查看这个包中的所有内容了
- Java for LeetCode 060 Permutation Sequence
The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the p ...
- Cocos2d-JS游戏导演
什么是游戏的导演 具体来说,Cocos2d-JS中的导演是一个对象,它负责设置游戏的运行环境,控制游戏的住循环并且管理场景和场景的切换. 导演的任务 Cocos2d-JS中导演对象名为:cc.dire ...